用LINQ查找对称差异 [英] Finding symmetric difference with LINQ
问题描述
我有两个集合a
和b
.我想计算a
或b
中的项目集,但不能同时计算两者(逻辑异或).有了LINQ,我可以提出以下建议:
I have two collections a
and b
. I would like to compute the set of items in either a
or b
, but not in both (a logical exclusive or). With LINQ, I can come up with this:
IEnumerable<T> Delta<T>(IEnumerable<T> a, IEnumerable<T> b)
{
return a.Except (b).Union (b.Except (a));
}
我想知道是否还有其他更有效或更紧凑的方式来产生这两个集合之间的差异.
I wonder if there are other more efficient or more compact ways of producing the difference between the two collections.
乔恩·斯凯特(Jon Skeet)发布了第一个解决方案,该解决方案不依靠HashSet
保留项目的顺序.我想知道是否还有其他方法可以在输出中保留a
和b
的顺序.
Edit 1: Jon Skeet posted a first solution which does not preserve the order of the items by relying on a HashSet
. I wonder if there are other approaches which would preserve the order of a
and b
in the output.
推荐答案
直接使用HashSet<T>
-它具有SymmetricExceptWith
方法:
Use HashSet<T>
directly - it has a SymmetricExceptWith
method:
HashSet<T> data = new HashSet<T>(a);
data.SymmetricExceptWith(b);
如果您想维护订单,这是一种替代方法:
If you want to maintain the order, here's an alternative:
HashSet<T> data = new HashSet<T>(a);
data.IntersectWith(b);
foreach (T t in a.Concat(b))
{
if (!data.Contains(t))
{
yield return t;
}
}
这有以下重要区别:
-
a
和b
都重复两次.在某些情况下,这可能是一件非常糟糕的事情-您可以在每个参数上调用ToList
,以保留缓冲区. -
如果
a
或b
中存在重复项,则将产生多次.如果要避免这种情况,可以保留一组已经产生的值.此时,它等同于:
- Both
a
andb
are iterated over twice. In some cases that could be a very bad thing - you could callToList
on each of them to start with to retain a buffer. If there are duplicates in either
a
orb
, they will be yielded multiple times. If you wanted to avoid this you could keep a set of already-yielded values. At this point, it would be equivalent to:
a.Concat(b).Except(a.Intersect(b))
那仍然只是两个设置操作,而不是原始代码中的三个.
That's still only two set operations instead of the three in your original code though.
这篇关于用LINQ查找对称差异的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!