2 zhanghuiynx zhanghuiynx 于 2013.09.28 18:00 提问

c#中快速从3个DataTable中分别提取一个数据进行相加,获得我想要的值

【背景】:有三个DataTable,每个DataTable大约1.5万条数据。

【我的需求描述】:封装一个方法,参数1是我需要的值,参数2是偏差值,参数3、4、5分别是3个DataTable,参数6是一个允许的匹配次数(当然,有好的办法的话,这个参数可以不要),我的意思必须要很快的从3个DataTable中各抽出一行中的一列(也就是分别从3个DataTable中提取一个数),进行相加,3个数加得的总和应该在参数1的值减去偏差值到参数1的值加上偏差值这个范围内,并且我需要快速得到数据,比如2秒内,求最好的解决办法......(提醒:我要的是很快可以得到结果的办法,不是1分钟才能得到结果)

【再次累赘的说一下想完成的功能】:就是说:用户输入一个想得到的值(比如2500),然后用户输入一个允许的偏差值(比如500,正负偏差都可以就是说高于500以内或低于500以内都可以,当然,偏差值是0也可以),3个容器(DataTable或数组或集合都行,这里是由系统提供的固定数据),最终需要使用大家的方法而得到的索引分别代入3个容器中,以便从3个容器中分别取一个值出来,进行相加,使得加数属于该用户想得到的值(此时应在2000-3000范围内,含临界值)即可。

【我的其他要求】:必须是匹配速度非常快(最慢1-2秒)、准确、代码合理。如果用户每次都输入2500的需求值和500的偏差值,最终你们提供的方法所获得的索引不应该每次都一样,当然如果有特殊情况下只能匹配出一个的话是列外的,因为以现有的值来看,一般偏差值不是0的话,按道理是可以匹配出很多条的,但是,只要找到一个匹配,即可以直接返回了。方式不需要有多大的通用性,只要能满足该需求即可.

点击这里下载测试项目,写好了的,有数据直接可以测试 <-----■■■■■■■■■

【一些提示】:有人反映说我的数据有重复,其实告诉你们,里面有45041条,是没有重复的,只是weight有重复而已,我给你们的数据库删除了很多列,其他列是没有重复的。

【想封装的方法如下】:

    /// <summary>
    /// 获取自动匹配
    /// </summary>
    /// <param name="needValue">需要的值</param>
    /// <param name="deviationValue">允许的偏差值(正负)</param>
    /// <param name="dtFirst">第一个数据容器:DataTable</param>
    /// <param name="dtSecond">第二个数据容器:DataTable</param>
    /// <param name="dtThird">第三个数据容器:DataTable</param>
    /// <param name="reMatchCount">允许的匹配次数,如果有更好的办法,该参数可以取消掉</param>
    /// <returns>获得的结果,比如:三个DataTable的索引</returns>
    public object GetAutoMatch(double needValue, double deviationValue,
        DataTable dtFirst, DataTable dtSecond, DataTable dtThird, int reMatchCount)
    {
        //我们假设此时传来的参数值是:
        needValue=2500;
        deviationValue=500;
        dtFirst=第1个DataTable;//(是固定数据,当然,这里你理解成一个数组也行)
        dtSecond=第2个DataTable;//(是固定数据,当然,这里你理解成一个数组也行)
        dtThird=第3个DataTable;//(是固定数据,当然,这里你理解成一个数组也行)
        reMatchCount=99999;//暂时没用上,如果采用循环方式,可以考虑用上此参数

        //只要大家在三个DataTable中分别抽出一个数(也就是说任意三个索引)
        //加起来的值是我想要的,就匹配成功了
        int firstIndex = 0;//这里是关键,就是让大家帮我得到一个firstIndex 
        int secondIndex = 0;//这里是关键,就是让大家帮我得到一个secondIndex 
        int thirdIndex = 0;//这里是关键,就是让大家帮我得到一个thirdIndex 

        //问题就在这里,我需要大家想个办法出来,能在1秒钟内得到3个索引值,最重要的是,把索引值代入后面的if判断必须要满足条件,因为我事先分别知道3个DataTable的最大值和最小值,而且我限制了needValue、deviationValue了,按照我的限制规则加上你们得到的3个索引,匹配的结果是绝对能匹配成功的,如果匹配不出,那么代表你们帮我获取的3个索引值根本不正确。

        //按照以上传参的值,如果sum在2000-3000范围,就算匹配成功
        double sum = Convert.ToDouble(dtFirst.Rows[firstIndex]["Weight"]) +
            Convert.ToDouble(dtSecond.Rows[secondIndex]["Weight"]) + 
            Convert.ToDouble(dtThird.Rows[thirdIndex]["Weight"]);
        //如果找到任意一组匹配的项,就可以return了。
        if (sum == needValue
            //|| sum == needValue - deviationValue//这个不需要,因为后面是<=
            //|| needValue == sum - deviationValue//这个不需要,因为后面是<=
            ||sum - needValue <= deviationValue 
            || Math.Abs(needValue - sum) <= deviationValue)
        {
            return firstIndex+"|"+secondIndex+"|"+thirdIndex+"#"+sum;
        }
        return "-1|-1|-1#0";
        //建议大家看完后,给点评论什么的,说下您的建议。
        //感谢大家的帮助.......................  
        //手写的代码,有点累,而且有些内容多处累赘了,不好意思...           
    }

1个回答

aly1989
aly1989   2013.09.29 09:30

折半查找三个DataTable的中间值,然后相加验证。前提当然是有序的。

zhanghuiynx
zhanghuiynx 这是其中一个办法
4 年多之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!