C# 通过两个集合循环—性能和优化可能性

C# 通过两个集合循环—性能和优化可能性,c#,performance,algorithm,optimization,collections,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 t

这可能是一个非常常见的问题,有很多答案。我无法找到答案,因为我不太确定如何寻找答案

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

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
}
}
这是非常低效的,而且根据两个集合中对象的数量,速度会变慢

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

编辑:

我现在正在使用.NET4,所以我也对使用并行性来加速的建议感兴趣

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

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

如果您需要逐个检查所有变体,那么您无法做得更好。但是你可以并行循环。例如,如果您使用的是c#4.0,则可以使用并行foreach循环

你可以在这里找到一个例子


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

如果您确实必须为列表a中的每一项处理列表b中的每一项,那么所需时间将与
a.Count*b.Count
成比例。你没办法阻止它。添加并行处理将给您带来线性加速,但如果列表甚至相当大,这不会减少处理时间

这些列表有多大?您真的必须检查
a
b
的每个组合吗?你能给我们一些关于你试图解决的问题的更多信息吗?我怀疑有一种方法可以带来更有效的算法,它可以将处理时间减少几个数量级

发布更多信息后编辑

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

看看这些数字。如果
a
中有4000项,而
b
中有100000项,则嵌套循环将进行4亿次比较(
a.Count*b.Count
)。但是排序只是
nlogn
,合并是线性的。因此,排序和合并大约是
(a.Count*12)+(b.Count*17)+a.Count+b.Count
,或者大约是200万次比较。这大约快了200倍

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

你只需要找到更好的算法


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

首先,您使用第二个集合中第一个集合的值进行搜索是有原因的


例如,如果您想知道第二个集合中有一个值激发,则应将第二个集合放入哈希集中,这将允许您进行快速查找。创建哈希集并访问它就像循环集合的1对n一样。

如果我们并行化两个循环会怎么样?Parallel.ForEach(collectiona,currentA=>Parallel.ForEach(CollectionB,currentB=>{//do something}));好。。是:)以同样的方式,您可以并行化两个循环。。我不知道为什么我只考虑第二个取决于循环内部发生的事情。例如,如果你将B上的某个东西求和为a的属性。为了使并行化有效地工作,操作必须是原子的,最好不需要在内部循环上锁定,在外部循环上锁定vFerry littel。并行化可能不会加快它,但很容易使它变慢。如果你给我们一个逻辑例子,它必须发生在循环内部,我们也许能给你一些关于如何优化这个例子或“类型”的线索。@Tony Hopkins,我编辑了我的问题。我希望这些信息足够了。这些列表的长度介于4000到100000个对象之间。例如,我需要对组合执行的操作是比较某些业务规则上的两个对象(a和b)。有关这些业务规则的示例,请参见上面的编辑
Parallel.ForEach(a, currentA => Parallel.ForEach(b, currentB =>
                                                                {
             // do something with currentA and currentB
                                                                }));
foreach(var a in collection1){
Parallel.ForEach(collection2, b =>
            {

//do something with a and b
            } //close lambda expression
                 ); 
}