从列表中删除重复项的最有效方法

本文关键字:有效 方法 列表 删除 | 更新日期: 2023-09-27 17:50:06

假设我有一个具有重复值的列表,我想删除重复的值。

List<int> myList = new List<int>(Enumerable.Range(0, 10000));
// adding a few duplicates here
myList.Add(1); 
myList.Add(2);
myList.Add(3);

我找到了3种方法来解决这个问题:

List<int> result1 = new HashSet<int>(myList).ToList(); //3700 ticks
List<int> result2 = myList.Distinct().ToList(); //4700 ticks
List<int> result3 = myList.GroupBy(x => x).Select(grp => grp.First()).ToList(); //18800 ticks
//referring to pinturic's comment:
List<int> result4 = new SortedSet<int>(myList).ToList(); //18000 ticks

在这里关于SO的大多数答案中,Distinct方法被显示为"正确的方法",但HashSet总是更快!

我的问题:当我使用哈希集方法时,是否有什么我必须意识到的,是否有另一种更有效的方法?

从列表中删除重复项的最有效方法

这两种方法有很大的区别:

List<int> Result1 = new HashSet<int>(myList).ToList(); //3700 ticks
List<int> 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<TSource> Distinct<TSource>(this IEnumerable<TSource> source) {
    if (source == null) throw Error.ArgumentNull("source");
    return DistinctIterator<TSource>(source, null);
}
// Reference source http://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs,722
static IEnumerable<TSource> DistinctIterator<TSource>(IEnumerable<TSource> source, IEqualityComparer<TSource> comparer) {
    Set<TSource> set = new Set<TSource>(comparer);
    foreach (TSource element in source)
        if (set.Add(element)) yield return element;
}

所以最后Distinct()只是使用HashSet<>的内部实现(称为Set<>)来检查项的唯一性。

为了完整起见,我将添加一个链接到c# Distinct()方法是否保持序列的原始顺序完整?