嵌套循环通过2大数据集

时间:2011-11-15 21:02:49

标签: c# loops nested

我有来自不同系统的2组数据。一件约20,000条记录。一组数据是List<Objects>,另一组是来自我无法控制的系统的RecordSet(我只能请求记录并接收记录集)。

我需要通过将Recordset中的一些数据放入匹配的对象结构中来合并2之间的数据,匹配两个列表中存在的键。我试过的嵌套循环太慢了。

有没有快速的方法来获得匹配并转移到下一个对象?

编辑:现有代码

这是一个非常基本的嵌套循环

results = _sr.SearchLst(ut.ToString(), searchSettings);

foreach (BL.Packet ePacket in eList) {

    for (Int32 j = 0; j < results.Rows.Length; j++) {

        String acckey = results.Rows[0].Data.GetValue(1).ToString();
        String taskname = results.Rows[0].Data.GetValue(2).ToString();

        if (acckey == ePacket.RecKey.ToString()) {
            ePacket.prop1 = taskname;
            ePacket.prop2 = acckey;
        }
    }
}

我也看过Linq,但无法理解这两者是如何结合在一起的......我不确定Linq会不会更快。

解决方案:

这基本上就是我最终做的事情。

//move object from list to dictionary
var dict = eList.Cast<BaseObj>().ToDictionary(o => o.RecKey, o => o);

results = _sr.SearchLst(ut.ToString(), searchSettings);
if (results.Rows.Length > 0) {

    //loop through all rows in recordset
    for (Int32 j = 0; j < results.Rows.Length; j++) {
        id = Convert.ToInt32(results.Rows[j].Data.GetValue(1)); 
        taskname = results.Rows[j].Data.GetValue(2).ToString();

        if (dict.ContainsKey(id)) {
            //recordset id found in dictionary, so grab taskname
            ePacket = ((BL.Packet)dict[id]);
            ePacket.prop1 = taskname;
        }
    }
}

//move dictionary back to list
List<BaseObj> eListReturn = new List<BaseObj>(dict.Values);
return eListReturn;

感谢大家的帮助!

4 个答案:

答案 0 :(得分:3)

试试这个:

var Object = from o in Objects
             join r in RecordSet equal o.YourKey equal r.YourForeignKey
             select Object { x = r.YourProperty };

有关LINQ的其他参考,这里有101个样本:http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b

(旧留言供参考)

如果将info添加到单个IEnumerable(如List)中,则使用LINQ将两个部分连接起来。 像

这样的东西
var combinedData = from i in listItems
                   join r in recordSet on r.ID equals i.ID
                   select new { i.Name, r.Property };

这是使用LINQ http://www.dotnetperls.com/join的连接的链接 此外,针对.net平台的谷歌LINQ示例,有很多,并且它正在快速完成你正在寻找的东西。

在寻找类似线程的SO之后,我发现了一些非常有用的东西,我将在这里总结一下。问题是,我们不确定你想在循环的内括号中做什么。

我假设您只想要一组“小工具”,可以通过密钥与“小工具”列表结合使用。

如果你想将一堆小部件和小工具加入到一个新的whatsits对象中 - 也许你正在为图表构建一个平面表,或者使用这个例子:

var whatsits = from w in widgets
               join g in gadgets on w.gadgetID equal g.ID
               select new whatsit { name = w.name, id = w.ID };

如果你想让一些小工具加入小工具,其中小工具属性=某个值,然后对每个小工具进行操作,你首先要收集这些小工具,然后按照这样的方式覆盖新的集合:

var widgetList = from w in widgets
                 join g in gadgets on w.gadgetID equals g.ID
                 where g.Name = "whatsit"
                 select w;

foreach (widget w in widgetList)
{
    // Do a bunch of stuff to each widget
}

注意,可能值得在上面的LINQ上进行性能测试,看看它是先运行更好的小部件,还是先在小部件中运行小工具。

答案 1 :(得分:2)

在内存中的列表集合上使用Dictionary<TypeOfKey, SomeObject>,使用键作为键填充字典,将对象作为值填充。

循环记录集。使用字典,您可以对匹配元素执行O(1)查找,这样就可以消除内存集合中的循环。

答案 2 :(得分:0)

您可以在RecordSet对象及其API上编写一个抽象层,允许使用密钥进行访问。它有点像从键到RecordSet的字典。

您将有两次迭代 - 每个集合一次。两次迭代是O(N),而嵌套循环是O(N ^ 2)。

答案 3 :(得分:0)

如果记录集按排序顺序返回值,例如

值键

'val'| 1

'val2'| 2

'val2'| 3

'val2'| 4

然后你可以进行排序合并连接。这是一个伪代码

while (!endofRecordset || !endofMyCollection) do
   if (recorset[rIndex].Key==myList[lIndex].Key)
       Join(recorset[rIndex], myList[lIndex])
   else if (recordset[rIndex] > myList[lIndex])
       lIndex++
   else 
       rIndex++
end while

修改

这里有关于sort-merge join的更多信息,以及c#

中的示例