除了与Distinct有类似的效果?

我刚刚发现Except()将从第一个列表中删除第二个列表中的所有元素,但它还具有使得返回结果中的所有元素都不同的效果。

我正在使用的简单方法是Where(v => !secondList.Contains(v))

任何人都可以向我解释为什么这是行为,如果可能的话,请指出解释这个问题的文档?

Except函数的文档说明:

通过使用默认的相等比较器来比较值,生成两个序列的集合差异。

两组的设定差异被定义为第一组中未出现在第二组中的成员。

这里的重要词是set , 定义为:

…一个抽象的数据结构,可以存储某些值,没有任何特定的顺序,也没有重复的值……

因为Except被记录为基于集合的操作,所以它还具有使结果值不同的效果。

你写了:

我正在使用的简单方法是Where(v => !secondList.Contains(v))

执行此操作时,仍然使用secondList完成secondList

例如:

 var firstStrings = new [] { "1", null, null, null, "3", "3" }; var secondStrings = new [] { "1", "1", "1", null, null, "4" }; var resultStrings = firstStrings.Where(v => !secondStrings.Contains(v)); // 3, 3 

我创建了一个扩展方法,根本没有任何区别。 使用考试:

 var result2Strings = firstStrings.ExceptAll(secondStrings).ToList(); // null, 3, 3 

这就是它的作用:

在此处输入图像描述

这是来源:

 public static IEnumerable ExceptAll( this IEnumerable first, IEnumerable second) { // Do not call reuse the overload method because that is a slower imlementation if (first == null) { throw new ArgumentNullException("first"); } if (second == null) { throw new ArgumentNullException("second"); } var secondList = second.ToList(); return first.Where(s => !secondList.Remove(s)); } public static IEnumerable ExceptAll( this IEnumerable first, IEnumerable second, IEqualityComparer comparer) { if (first == null) { throw new ArgumentNullException("first"); } if (second == null) { throw new ArgumentNullException("second"); } var comparerUsed = comparer ?? EqualityComparer.Default; var secondList = second.ToList(); foreach (var item in first) { if (secondList.Contains(item, comparerUsed)) { secondList.Remove(item); } else { yield return item; } } } 

编辑:基于DigEmAll的评论更快的实现

 public static IEnumerable ExceptAll( this IEnumerable first, IEnumerable second) { return ExceptAll(first, second, null); } public static IEnumerable ExceptAll( this IEnumerable first, IEnumerable second, IEqualityComparer comparer) { if (first == null) { throw new ArgumentNullException("first"); } if (second == null) { throw new ArgumentNullException("second"); } var secondCounts = new Dictionary(comparer ?? EqualityComparer.Default); int count; int nullCount = 0; // Count the values from second foreach (var item in second) { if (item == null) { nullCount++; } else { if (secondCounts.TryGetValue(item, out count)) { secondCounts[item] = count + 1; } else { secondCounts.Add(item, 1); } } } // Yield the values from first foreach (var item in first) { if (item == null) { nullCount--; if (nullCount < 0) { yield return item; } } else { if (secondCounts.TryGetValue(item, out count)) { if (count == 0) { secondCounts.Remove(item); yield return item; } else { secondCounts[item] = count - 1; } } else { yield return item; } } } } 

我博客上的更多信息 (也是Intersect和Union的变体)