循环使用两个集合 - 性能和优化可能性

时间:2011-12-27 12:13:37

标签: c# performance algorithm optimization collections

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

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

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,所以我也对使用Parallelism提高速度的建议感兴趣。

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

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

4 个答案:

答案 0 :(得分:3)

如果您真的必须为列表a中的每个项目处理列表b中的每个项目,那么它将花费与a.Count * b.Count成比例的时间。你没有办法阻止它。添加并行处理将为您提供线性加速,但如果列表中等大,则不会在处理时间上产生影响。

这些名单有多大?你真的必须检查ab的每个组合吗?您能否提供一些有关您尝试解决的问题的更多信息?我怀疑有一种方法可以带来更高效的算法,这会使你的处理时间缩短一个数量级。

在发布更多信息后进行修改

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

看看数字。如果您的a中有4,000个项目且b中有100,000个项目,那么您的嵌套循环将进行4亿次比较(a.Count * b.Count)。但排序只是n log n,合并是线性的。因此,排序然后合并将大约(a.Count * 12) + (b.Count * 17) + a.Count + b.Count,或者在200万比较的附近。这大约快了200倍。

将其与您可以对并行处理执行的操作进行比较:仅提供线性加速。如果你有四个核心并且你获得了纯粹的线性加速,那么你只会把你的时间缩短四倍。更好的算法使用单个线程将时间缩短了200倍。

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

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

答案 1 :(得分:1)

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

答案 2 :(得分:1)

如果您需要逐个检查所有变体,则无法做更好的事情。但你可以平行循环。例如,如果您使用的是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
                 ); 
}

同样,您也可以并行第一个循环。

答案 3 :(得分:1)

首先,您要使用第二个集合中第一个集合中的值进行搜索。

例如,如果您想知道某个值在第二个集合中激发,您应该将第二个集合放在一个哈希集中,这样您就可以快速查找。创建HashSet并访问它就像1 vs n一样用于循环集合。