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
);
}