我很确定这是重复的,但我已经尝试了一切,但我似乎仍然无法得到差异。我有两个字符串列表:listA和listB。我正在尝试查找listA中不在B中的项目。
实施例: listA:“1”,“2”,“4”,“7” listB:“2”,“4” 我想要的输出是:“1”,“7”
这是我尝试的for循环和lambda表达式,但这些需要很长时间:
//these two approaches take too long for huge lists
foreach (var item in listA)
{
if (!listB.Contains(item))
diff.Add(id);
}
diff = listA.Where(id => !listB.Contains(id)).ToList();
//these don't give me the right differences
listA.Except(listB).ToList();
var set = new HashSet<string>(listA);
set.SymmetricExceptWith(listB);
答案 0 :(得分:6)
使用LINQ的Except
方法:
listA.Except(listB).ToList();
答案 1 :(得分:1)
listA.Except(listB).ToList();
应该给出正确答案,但
set.SymmetricExceptWith(listB);
不应该。 SymmetricExcept会使listA中的项目不在listB 加上 ListB中不在ListA中的项目。
答案 2 :(得分:1)
你发布的所有代码都应该可以正常运行,所以无论如何你都会写错误“这需要很长时间”然后我认为你有性能问题。
让我们做一个非常快速和肮脏的比较(你知道做一个好的性能测试是一个漫长的过程,自我推销:基准已经用this free tool完成)。假设:
SymmetricExceptWith
,如果没有,那么它的结果与Except
相比非常不同)。如果这是一个错误,只需忽略SymmetricExceptWith
的测试。两个 20,000个随机项列表(测试重复100次,然后是平均值,发布模式)。
Method Time [ms] Contains *1 49.4 Contains *2 49.0 Except 5.9 SymmetricExceptWith *3 4.1 SymmetricExceptWith *4 2.5
注意:
1 与foreach循环
2 循环用于
3 Hashset创建测量
4 未测量Hashset创建。我将此作为参考,但如果您没有第一个列表作为Hashset,则不能忽略创建时间。
我们看到Contains()
方法非常慢,所以我们可以将它放在更大的测试中(无论如何我检查过它的性能不会变得更好甚至可比)。让我们看看 1,000,000项列表会发生什么。
Method Time [ms] Except 244.4 SymmetricExceptWith 259.0
让我们尝试使其并行(请注意,对于此测试,我使用的是旧的Core 2 Duo 2 GHz):
Method Time [ms] Except 244.4 SymmetricExceptWith 259.0 Except (parallel partitions) 301.8 SymmetricExceptWith (p. p.) 382.6 Except (AsParallel) 274.4
并行性能更差,LINQ Except现在是最佳选择。让我们看看它如何在更好的CPU (Xeon 2.8 GHz,四核)上运行。另请注意,如此大量的数据缓存大小不会对测试造成太大影响。
Method Time [ms] Except 127.4 SymmetricExceptWith 149.2 Except (parallel partitions) 208.0 SymmetricExceptWith (p. p.) 170.0 Except (AsParallel) 80.2
总结一下:对于相对较小的列表SymmetricExceptWith()
会表现得更好,对于大型列表Except()
总是更好。如果您的目标是使用现代多核CPU,那么并行实施将会更好地扩展。在代码中:
var c = a.Except(b).ToList();
var c = a.AsParallel().Except(b.AsParallel()).ToList();
请注意,如果您不需要List<string>
作为结果且IEnumerable<string>
足够,那么性能将大大提高(并行执行的差异会更大)。
当然,这两行代码并不是最优的,并且可以大大增加(如果它确实对性能至关重要,那么您可以选择ParallelEnumerable.Except()
实现作为您自己特定的高度优化例程的起点。)