2011-11-15 62 views
0

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

我需要将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会更快。

SOLUTION:

这里基本上是我终于实现了。

//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; 

感谢大家的帮助!

+0

您是否尝试过使用LINQ加入他们? – CaffGeek

+1

请发布您的现有代码。 –

+0

你提到的关键字的基础类型是什么 - “匹配存在于......中的关键字”? – sll

回答

2

的列表中收集你的内存有使用Dictionary<TypeOfKey, SomeObject>,填充使用键键和对象值的字典。

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

+0

将列表转换为字典(或将列表添加到字典)处理速度快吗? – Metallicraft

+0

你可以扩展你的想法吗?谢谢 – Metallicraft

0

你可以写在Recordset对象和他们的API,它允许使用一键访问的抽象层。它有点像从RecordSet的关键字到字典。

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

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

(仅供参考旧消息)

使用LINQ加入两件,如果信息成单个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 此外,谷歌LINQ的实例为您的.NET平台,有很多在那里,这是相当快正好做你在找什么。

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

我假设你只需要一组可以通过一键“小玩意”的名单中加入了“小工具”的。

如果你想了一堆widgets和gadgets的加入到一个新的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 }; 

如果你想获得一个一串窗口小部件加入了与小工具,其中一个小工具属性=一些值,然后做每个小工具,您首先收集的小玩意,然后的foreach在新的集合,像这样:

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上做一个性能测试来看看它首先运行更好的窗口小部件,或首先在联接中运行小工具。

+0

谢谢,我也会试试,看看它是否有帮助。 – Metallicraft

+0

我更新了示例以在内部括号中包含一些代码。谢谢 – Metallicraft

+0

好吧,根据括号中的代码,你所做的就是将两个不同的类聚合成一个新的平板类,可以这么说。我会使用LINQ示例#2,它将全部删除对foreach循环的需要。 – EtherDragon

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 

编辑:

这里更多信息与例如在C#中约sort-merge join

+0

不,他们没有排序:(。 – Metallicraft