使用 LINQ 查找对称差异
我有两个集合 a
和 b
。我想计算 a
或 b
中的项目集,但不能同时计算两者(逻辑异或)。通过 LINQ,我可以想到:
IEnumerable<T> Delta<T>(IEnumerable<T> a, IEnumerable<T> b)
{
return a.Except (b).Union (b.Except (a));
}
我想知道是否有其他更有效或更紧凑的方法来产生两个集合之间的差异。
编辑 1:Jon Skeet 发布了第一个解决方案,该解决方案不依赖 HashSet
来保留项目的顺序。我想知道是否有其他方法可以保留输出中 a
和 b
的顺序。
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.
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
直接使用
HashSet
- 它有一个SymmetricExceptWith
方法:编辑:如果您想保持顺序,这里有一个替代方案:
这有以下重要区别:
b
迭代两次。在某些情况下,这可能是一件非常糟糕的事情 - 您可以对每个对象调用ToList
以保留缓冲区。如果
a
或b
中有重复项,它们将被产生多次。如果您想避免这种情况,您可以保留一组已经生成的值。此时,它相当于:不过,这仍然只有两个集合操作,而不是原始代码中的三个。
Use
HashSet<T>
directly - it has aSymmetricExceptWith
method:EDIT: If you want to maintain the order, here's an alternative:
This has the following important differences:
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:That's still only two set operations instead of the three in your original code though.
鉴于 a.Except(b) 和 b.Except(a) 不相交,您可以使用
concat
而不是union
,从而保存集合运算符(以及concat< /code> 效率更高)。
这仍然会在每个列表中运行两次。
Given a.Except(b) and b.Except(a) are disjoint, you can use
concat
instead ofunion
, saving a set operator (andconcat
is more efficient).This still runs through each list twice.
我们公司的一个项目也有类似的需求,所以我们编写了这个扩展:
它比较两个集合的元素(使用或不使用
IEqualityComparer
,由您选择)。EnumerablePair
,包含位于leftOperand
或rightOperand
中的对象,但不能同时包含在两者中 (XOR)。EnumerablePair.Left
包含位于leftOperand
中但不在rightOperand
中的对象。EnumerablePair.Right
包含位于rightOperand
中但不在leftOperand
中的对象。您可以使用如下扩展:
xorList
、leftXor
和rightXor
是IEnumerable
。We had a similar need for a project in my company, so we wrote this extension:
It compares elements of two collections (using an
IEqualityComparer
or not, at your choice).EnumerablePair<T>
, contains objects that are inleftOperand
orrightOperand
, but not both (XOR).EnumerablePair<T>.Left
contains objects that are inleftOperand
but not inrightOperand
.EnumerablePair<T>.Right
contains objects that are inrightOperand
but not inleftOperand
.You can use the extension like this :
xorList
,leftXor
andrightXor
areIEnumerable<T>
.