Todas las soluciones mencionadas hasta ahora realizan un GroupBy. Incluso si solo necesito el primer duplicado, todos los elementos de las colecciones se enumeran al menos una vez.
La siguiente función de extensión deja de enumerar tan pronto como se encuentra un duplicado. Continúa si se solicita un próximo duplicado.
Como siempre en LINQ hay dos versiones, una con IEqualityComparer y otra sin ella.
public static IEnumerable<TSource> ExtractDuplicates(this IEnumerable<TSource> source)
{
return source.ExtractDuplicates(null);
}
public static IEnumerable<TSource> ExtractDuplicates(this IEnumerable<TSource source,
IEqualityComparer<TSource> comparer);
{
if (source == null) throw new ArgumentNullException(nameof(source));
if (comparer == null)
comparer = EqualityCompare<TSource>.Default;
HashSet<TSource> foundElements = new HashSet<TSource>(comparer);
foreach (TSource sourceItem in source)
{
if (!foundElements.Contains(sourceItem))
{ // we've not seen this sourceItem before. Add to the foundElements
foundElements.Add(sourceItem);
}
else
{ // we've seen this item before. It is a duplicate!
yield return sourceItem;
}
}
}
Uso:
IEnumerable<MyClass> myObjects = ...
// check if has duplicates:
bool hasDuplicates = myObjects.ExtractDuplicates().Any();
// or find the first three duplicates:
IEnumerable<MyClass> first3Duplicates = myObjects.ExtractDuplicates().Take(3)
// or find the first 5 duplicates that have a Name = "MyName"
IEnumerable<MyClass> myNameDuplicates = myObjects.ExtractDuplicates()
.Where(duplicate => duplicate.Name == "MyName")
.Take(5);
Por todas estas declaraciones linq la colección sólo se analiza hasta que se encuentren los elementos solicitados. El resto de la secuencia no se interpreta.
en mi humilde opinión que es un impulso de eficiencia a considerar.
Si la entrada es "1", "1", "1" ¿cuántos elementos debería haber en la lista resultante? –
@Mark Bayers: la lista resultante debe contener '" 1 "," 1 "' :-) –
Casi lo mismo: http://stackoverflow.com/questions/3239523/how-to-find-and-remove-duplicate -objects-in-a-collection-using-linq – nawfal