我有两个不同的列表,需要比较这两个列表并获取除了这两个列表之间的交集以外的所有内容。如何实现这个功能(使用C#)?
我有两个不同的列表,需要比较这两个列表并获取除了这两个列表之间的交集以外的所有内容。如何实现这个功能(使用C#)?
如果您的意思是除了交集(即对称差异)之外的所有东西的集合,您可以尝试:
var set = new HashSet<Type>(list1);
set.SymmetricExceptWith(list2);
var differences = listA.Except(listB).Union(listB.Except(listA));
如果你想获取除了并集之外的所有内容:
var allButUnion = new List<MyClass>();
(并集包含了两个列表中的所有元素 - 除了并集之外,剩下的部分是空集...)
var allButIntersection = a.Union(b).Except(a.Intersect(b));
那可能会有些低效,但它相当简单地表明了您的意思(当然,假设我正确地理解了您的意思)。
这是一个通用的扩展方法。Rosetta Code使用Concat,而Djeefther Souza认为这更有效率。
public static class LINQSetExtensions
{
// Made aware of the name for this from Swift
// https://dev59.com/XnI-5IYBdhLWcg3wxbjv
// Generic implementation adapted from https://www.rosettacode.org/wiki/Symmetric_difference
public static IEnumerable<T> SymmetricDifference<T>(this IEnumerable<T> first, IEnumerable<T> second)
{
// I've used Union in the past, but I suppose Concat works.
// No idea if they perform differently.
return first.Except(second).Concat(second.Except(first));
}
}
我实际上没有对此进行基准测试。我认为这取决于Union和Concat是如何实现的。在我的理想世界中,.NET使用不同的算法来处理不同的数据类型或集合大小,但对于IEnumerable,它无法提前确定集合大小。
另外,你可以忽略我的回答- Jon Skeet表示HashSet方法“非常好-这看起来是我做到最好的方式。”
像这样吗?
String[] one = new String[] { "Merry", "Metal", "Median", "Medium", "Malfunction", "Mean", "Measure", "Melt", "Merit", "Metaphysical", "Mental", "Menial", "Mend", "Find" };
String[] two = new String[] { "Merry", "Metal", "Find", "Puncture", "Revise", "Clamp", "Menial" };
List<String> tmp = one.Except(two).ToList();
tmp.AddRange(two.Except(one));
String[] result = tmp.ToArray();
使用 Except:
List<int> l1 = new List<int>(new[] { 1, 2, 3, 4 });
List<int> l2 = new List<int>(new[] { 2, 4 });
var l3 = l1.Except(l2);
var theUnion = list1.Concat(list2);
var theIntersection = list1.Intersect(list2);
var theSymmetricDifference = theUnion.Except(theIntersection);