嵌套循环遍历2个大数据集



我有两组来自不同系统的数据。大约20000张唱片。一组数据是List<Objects>,另一组是来自我无法控制的系统的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;

感谢大家的帮助!

试试这个:

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

(旧消息参考)

使用LINQ将这两部分if info连接成一个IEnumerable(类似于List)。就像

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的例子,有很多,它在做你正在寻找的东西时相当快。

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

我假设你只想要一组"小部件",它们可以通过一个键连接到一个"小部件"列表。

如果你想把一堆小部件和小工具连接到一个新的whatsit对象中——也许你正在为图表或其他东西构建一个平面表格,使用这个例子:

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上做一个性能测试可能是值得的,看看它是小部件优先运行更好,还是小部件优先在连接中运行更好。

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

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

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

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

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

价值的关键

'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

编辑:

这里有更多关于排序合并连接的信息,用c#为例

最新更新