这可能是一个非常普遍的问题,有很多答案。我无法得到答案,因为我不太确定如何搜索它。
我有两个对象集合 - 都来自数据库,在某些情况下,这些集合具有相同的对象类型。此外,我需要为这些集合的每个组合执行一些操作。所以,例如:
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.这是我需要执行的操作之一。 (可以使用此类从子类配置操作)。
答案 0 :(得分:3)
如果您真的必须为列表a中的每个项目处理列表b中的每个项目,那么它将花费与a.Count * b.Count
成比例的时间。你没有办法阻止它。添加并行处理将为您提供线性加速,但如果列表中等大,则不会在处理时间上产生影响。
这些名单有多大?你真的必须检查a
和b
的每个组合吗?您能否提供一些有关您尝试解决的问题的更多信息?我怀疑有一种方法可以带来更高效的算法,这会使你的处理时间缩短一个数量级。
在发布更多信息后进行修改
我知道您发布的示例只是一个示例,但它表明您可以为至少某些情况找到更好的算法。在此特定示例中,您可以按名称对a
和b
进行排序,然后进行直接合并。或者,您可以将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一样用于循环集合。