2009-07-15 3 views
4

Hat jemand eine gute und effiziente Erweiterungsmethode zum Finden, ob eine Sequenz von Elementen irgendwelche Duplikate hat?C#: Eine gute und effiziente Implementierung von IEnumerable <T> .HasDuplicates

Ich denke, ich könnte return subjects.Distinct().Count() == subjects.Count() in eine Erweiterungsmethode setzen, aber irgendwie fühlt, dass es einen besseren Weg geben sollte. Diese Methode müsste Elemente zweimal zählen und alle district Elemente aussortieren. Eine bessere Implementierung sollte True für das erste gefundene Duplikat zurückgeben. Irgendwelche guten Vorschläge?

stelle ich mir die Umrisse so etwas wie dies sein könnte:

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) 
{ 
    ... 
} 

aber nicht ganz sicher, wie eine intelligente Umsetzung wäre es ...

Antwort

13
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; 
} 
+0

Jetzt sehen * das * ist ziemlich clever ... wird versuchen, dass man aus! – Svish

+1

Das könnte praktisch sein ... Ich glaube nicht, dass HashSet im kompakten Framework unterstützt wird, aber ... grrrrr. –

+0

Sie können das gleiche mit 'Dictionary < T, K >' tun, aber es ist ein bisschen weniger Speicher effizient. 'Dictionary < T, K > .Add' gibt kein' bool' zurück, aber seine 'Count'-Eigenschaft wäre trivial schnell auf Kosten von ein paar Zeilen mehr Code zu überprüfen. –

1

Ich denke, die einfachste Erweiterung Methode ist folgende.

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; 
    } 
    } 
} 
+0

Denken Sie, dass man eine return-Anweisung vermisst, sowie die Gegenseite zurückgibt, was es sollte? Wie auch immer, sehr ähnlich zu der anderen Antwort und Sie haben genug rep so akzeptiert die andere Antwort, p – Svish

4

Dies ist im Produktionscode. Works great:

public static bool HasDuplicates<T>(this IEnumerable<T> sequence) { 
    var set = new HashSet<T>(); 
    return !sequence.All(item => set.Add(item)); 
} 
+0

Sieht aus, um die ziemlich genau das gleiche wie meine angenommene Antwort, außer ein bisschen kürzer. Interessant :) – Svish

+0

Ja, derselbe Ansatz wie die erste Antwort (von 280Z28); wollte nicht anders vorschlagen. –