c# - repetidos - La forma más eficiente de eliminar duplicados de una lista
eliminar registros duplicados de una lista c# (1)
Digamos que tengo una lista con valores duplicados y quiero eliminar los duplicados.
List<int> myList = new List<int>(Enumerable.Range(0, 10000));
// adding a few duplicates here
myList.Add(1);
myList.Add(2);
myList.Add(3);
He encontrado 3 enfoques para resolver esto:
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
En la mayoría de las respuestas aquí en SO, el enfoque Distinct se muestra como el "correcto", ¡pero el HashSet siempre es más rápido!
Mi pregunta: ¿hay algo de lo que deba estar consciente cuando uso el enfoque HashSet y hay otra forma más eficiente?
Hay una gran diferencia entre estos dos enfoques:
List<int> Result1 = new HashSet<int>(myList).ToList(); //3700 ticks
List<int> Result2 = myList.Distinct().ToList(); //4700 ticks
El primero puede (probablemente) cambiará el orden de los elementos de los elementos devueltos de la List<>
: Result1
no estará en el mismo orden de los de myList
. El segundo mantiene el pedido original.
Probablemente no hay una manera más rápida que la primera.
Probablemente no hay "más correcto" (para una cierta definición de "correcto" basado en el pedido) que el segundo.
(El tercero es similar al segundo, solo que más lento)
Solo por curiosidad, el Distinct()
es:
// 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;
}
Así que al final, Distinct()
simplemente usa una implementación interna de un HashSet<>
(llamado Set<>
) para verificar la singularidad de los elementos.
Para completar, agregaré un enlace a la pregunta ¿El método C # Distinct () mantiene el orden original de la secuencia intacto?