循环遍历两个集合——性能和优化的可能性

本文关键字:性能 优化 可能性 集合 两个 遍历 循环 | 更新日期: 2023-09-27 18:18:48

这可能是一个非常常见的问题,有很多答案。我不能得到一个答案,因为我不太确定如何搜索它。

我有两个对象集合——都来自数据库,在某些情况下,这些集合具有相同的对象类型。此外,我需要对这些集合的每个组合执行一些操作。例如:

foreach(var a in collection1){
 foreach(var b in collection2){
   if(a.Name == b.Name && a.Value != b.Value)
      //do something with this combination
   else 
      //do something else
}
}

这是非常低效的,并且它会根据两个集合中的对象数量而变慢。

解决这类问题的最好方法是什么?

编辑:

我目前正在使用。net 4,所以我也对使用并行来加快速度的建议感兴趣。

编辑2:我在上面添加了一个需要对每个对象组合执行的业务规则示例。但是,示例中定义的业务规则可能有所不同。

编辑3:例如,在循环中将完成以下操作:如果满足业务规则(见上文),将在数据库中创建一条记录,其中包含对对象a和对象b的引用。这是我需要执行的操作之一。(操作可以从使用这个类的子类配置)。

循环遍历两个集合——性能和优化的可能性

如果你真的需要为列表a中的每个项目处理列表b中的每个项目,那么它将花费与a.Count * b.Count成正比的时间。你无法阻止它的发生。添加并行处理将为您提供线性加速,但如果列表非常大,则不会对处理时间产生影响。

这些列表有多大?你真的要检查ab的每一个组合吗?你能给我们提供更多关于你正在解决的问题的信息吗?我怀疑有一种方法可以带来更有效的算法,可以将处理时间减少几个数量级。

在更多信息发布后编辑

我知道你发布的例子只是一个例子,但它表明你可以找到一个更好的算法至少一些情况下。在这个特定的示例中,您可以按名称对ab进行排序,然后进行直接合并。或者,您可以将b排序到一个数组或列表中,并使用二进制搜索来查找名称。这两个选项中的任何一个都比嵌套循环执行得好得多。好得多,事实上,你可能不需要为并行化而烦恼。

看这些数字。如果你的a有4000个元素,b有100000个元素,你的嵌套循环将进行4亿次比较(a.Count * b.Count)。但是排序只是n log n,并且归并是线性的。所以排序然后归并大约是(a.Count * 12) + (b.Count * 17) + a.Count + b.Count,或者说大约200万次比较。大约快了200倍。

与并行处理相比:只有线性加速。如果你有四个核心,并且你得到了一个纯粹的线性加速,你只会把你的时间减少四倍。更好的算法在单线程情况下将时间缩短了200倍。

你只需要找到更好的算法。

LINQ可能也提供了一个很好的解决方案。我不是LINQ的专家,但它似乎应该能够快速完成这样的工作。

如果你需要一个一个地检查所有的变量,你不能做得更好。但是你可以平行这些循环。例如,如果你正在使用c# 4.0,你可以使用并行foreach循环。

你可以在这里找到一个例子…http://msdn.microsoft.com/en-us/library/dd460720.aspx

foreach(var a in collection1){
Parallel.ForEach(collection2, b =>
            {
//do something with a and b
            } //close lambda expression
                 ); 
}

以同样的方式你也可以并行第一个循环

首先,在第二个集合中搜索第一个集合中的值是有原因的。

例如,如果你想知道一个值在第二个集合中激发,你应该把第二个集合放在一个哈希集中,这将允许你做一个快速查找。创建HashSet并访问它就像1 vs n循环集合。

Parallel.ForEach(a, currentA => Parallel.ForEach(b, currentB =>
                                                                {
             // do something with currentA and currentB
                                                                }));