从List中删除重复项的最有效方法
假设我有一个包含重复值的List,我想删除重复项。
List myList = new List(Enumerable.Range(0, 10000)); // adding a few duplicates here myList.Add(1); myList.Add(2); myList.Add(3);
我找到了3种方法来解决这个问题:
List result1 = new HashSet(myList).ToList(); //3700 ticks List result2 = myList.Distinct().ToList(); //4700 ticks List result3 = myList.GroupBy(x => x).Select(grp => grp.First()).ToList(); //18800 ticks //referring to pinturic's comment: List result4 = new SortedSet(myList).ToList(); //18000 ticks
在SO的大多数答案中, Distinct方法显示为“正确的”,但HashSet总是更快!
我的问题:当我使用HashSet方法时,有什么我必须要注意的,还有另一种更有效的方法吗?
这两种方法之间存在很大差异:
List Result1 = new HashSet (myList).ToList(); //3700 ticks List Result2 = myList.Distinct().ToList(); //4700 ticks
第一个可以(可能)更改返回的List<>
元素的顺序: Result1
元素与myList
的元素的顺序不同。 第二个保持原始排序。
可能没有比第一个更快的方式。
对于第二个,可能没有“更正确”(对于基于排序的“正确”的某种定义)。
(第三个类似于第二个,只是更慢)
出于好奇, Distinct()
是:
// Reference source http://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs,712 public static IEnumerable Distinct (this IEnumerable source) { if (source == null) throw Error.ArgumentNull("source"); return DistinctIterator (source, null); } // Reference source http://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs,722 static IEnumerable DistinctIterator (IEnumerable source, IEqualityComparer comparer) { Set set = new Set (comparer); foreach (TSource element in source) if (set.Add(element)) yield return element; }
所以最后Distinct()
只是使用HashSet<>
(称为Set<>
)的内部实现来检查项的唯一性。
为了完整起见,我将添加一个问题的链接C#Distinct()方法保持序列的原始排序完整吗?