C #: Uma boa e eficiente implementação de IEnumerable .HasDuplicates
-
16-09-2019 - |
Pergunta
Alguém tem uma boa e eficiente método de extensão para encontrar se uma seqüência de itens tem todas as duplicatas?
Acho que eu poderia colocar return subjects.Distinct().Count() == subjects.Count()
em um método de extensão, mas tipo de considera que deve haver uma maneira melhor. Esse método teria de contar elementos duas vezes e resolver todos os elementos distict. A melhor implementação deve retornar true no primeiro duplicado que encontra. Alguma sugestão boa?
Eu imagino que o esboço poderia ser algo como isto:
public static bool HasDuplicates<T>(this IEnumerable<T> subjects)
{
return subjects.HasDuplicates(EqualityComparer<T>.Default);
}
public static bool HasDuplicates<T>(this IEnumerable<T> subjects, IEqualityComparer<T> comparer)
{
...
}
Mas não tem certeza de como uma implementação inteligente de que seria ...
Solução
public static bool HasDuplicates<T>(this IEnumerable<T> subjects)
{
return HasDuplicates(subjects, EqualityComparer<T>.Default);
}
public static bool HasDuplicates<T>(this IEnumerable<T> subjects, IEqualityComparer<T> comparer)
{
HashSet<T> set = new HashSet<T>(comparer);
foreach (T item in subjects)
{
if (!set.Add(item))
return true;
}
return false;
}
Outras dicas
Este é no código de produção. Funciona muito bem:
public static bool HasDuplicates<T>(this IEnumerable<T> sequence) {
var set = new HashSet<T>();
return !sequence.All(item => set.Add(item));
}
Eu acho que o método de extensão mais simples é o seguinte.
public static bool HasDuplicates<T>(this IEnumerable<T> enumerable) {
var hs = new HashSet<T>();
foreach ( var cur in enumerable ) {
if ( !hs.Add(cur) ) {
return false;
}
}
}