C#确定列表中的重复

要求:在未sorting的列表中,确定是否存在重复。 我会这样做的典型方法是一个n平方的嵌套循环。 我想知道别人怎么解决这个问题。 Linq中有一个优雅的高性能方法吗? 通用的lambda或比较器会很好。

除非我失去了一些东西,那么你应该能够用Distinct()简单地实现一些东西。 当然,这不会是你想到的最复杂的实现,但它会告诉你是否有任何重复被删除:

 var list = new List<string>(); // Fill the list if(list.Count != list.Distinct().Count()) { // Duplicates exist } 

根据Eric White关于如何使用LINQ查找重复项的文章:

查找重复项的简单方法是编写一个按标识符分组的查询,然后筛选具有多个成员的组。 在下面的例子中,我们想知道4和3是重复的:

 int[] listOfItems = new[] { 4, 2, 3, 1, 6, 4, 3 }; var duplicates = listOfItems .GroupBy(i => i) .Where(g => g.Count() > 1) .Select(g => g.Key); foreach (var d in duplicates) Console.WriteLine(d); // 4,3 

将所有项目放置在一个集合中,如果集合的计数与列表的计数不同,则会有重复。

 bool hasDuplicates<T>(List<T> myList) { var hs = new HashSet<T>(); for (var i = 0; i < myList.Count; ++i) { if (!hs.Add(myList[i])) return true; } return false; } 

因为没有必要通过所有的列表,所以应该比Distinct更有效率。

如果复本存在于列表的早期,为了允许短路,可以添加HashSet<T>并检查其.Add方法的返回值。

通过使用.Any你可以短暂枚举只要你find一个重复。

这是C#和VB中的LINQ扩展方法:

CSHARP:

 public static bool ContainsDuplicates<T>(this IEnumerable<T> enumerable) { var knownKeys = new HashSet<T>(); return enumerable.Any(item => !knownKeys.Add(item)); } 

Visual Basic:

 <Extension> Public Function ContainsDuplicates(Of T)(ByVal enumerable As IEnumerable(Of T)) As Boolean Dim knownKeys As New HashSet(Of T) Return enumerable.Any(Function(item) Not knownKeys.Add(item)) End Function 

注意 :要检查是否没有重复,只需将Any更改为All

沿着这些线的东西是相对简单的,并会为您提供重复计数。

 var something = new List<string>() { "One", "One", "Two", "Three" }; var dictionary = new Dictionary<string, int>(); something.ForEach(s => { if (dictionary.ContainsKey(s)) { dictionary[s]++; } else { dictionary[s] = 1; } }); 

我想这与Distinct的实现类似,虽然我不确定。

您可以使用IEnumerable的Distinct()扩展方法

如果您使用整数或sorting良好的集合,请使用O(nlog n)性能的二叉树。

或者,find另一种更快的sorting方法,然后检查每个值是否与前一个值不同。

使用Enumerable.AnyHashSet.Add像:

 List<string> list = new List<string> {"A", "A", "B", "C", "D"}; HashSet<string> hashSet = new HashSet<string>(); if(list.Any(r => !hashSet.Add(r))) { //duplicate exists. } 

如果项目已经存在于HashSet中, HashSet.Add将返回false 。 这不会遍历整个列表。

您可以使用IEnumerable.GroupBy方法。

 var list = new List<string> {"1", "2","3", "1", "2"}; var hasDuplicates = list.GroupBy(x => x).Any(x => x.Skip(1).Any());