2013-06-24 4 views
17

Ich muss suchen und entfernen Sie die Duplikate aus einer Liste von Tupeln. Grundsätzlich ist meine Struktur wie das gemacht:Suchen und Löschen von Duplikaten in der Liste der Tupel in C#

List<Tuple<string, string>> myList = new List<Tuple<string, string>>(); 

**** 

private void FillStructure() 
{ 
    myList.Add(Tuple.Create<string, string>("A", "B")); 
    myList.Add(Tuple.Create<string, string>("A", "C")); 
    myList.Add(Tuple.Create<string, string>("C", "B")); 
    myList.Add(Tuple.Create<string, string>("C", "B")); // Duplicate 
    myList.Add(Tuple.Create<string, string>("A", "D")); 

    FindAndRemoveDuplicates(myList); 
} 

private void FindAndRemoveDuplicates(List<Tuple<string, string>> myList) 
{ 
     // how can I perform this ? 
} 

Ich kann kein Wörterbuch verwenden, weil ich die gleichen Schlüssel, aber unterschiedliche Werte haben können! Vielen Dank im Voraus

Antwort

19

Sie Distinct() Methode von LINQ verwenden können, wie folgt aus:

myList = myList.Distinct().ToList(); 

Beachten Sie, dass dies die Liste neu erstellen würde, anstatt die Duplikate an Ort und Stelle zu entfernen.

+0

Die Lösung war so einfach! Vielen Dank! :) – davideberdin

0

Verwenden distinct() Methode:

myList.Distinct().ToList(); 
0

Wenn Sie eine Lösung wollen, die die Liste an Ort und Stelle ändert, können Sie die Verwendung eines HashSet<T> (oder für ältere Frameworks eine Dictionary<Tuple<string, string>, object> und ignorieren den Wert) machen:

var existing = new HashSet<Tuple<string, string>>(); 

for (int i = myList.Count - 1; i >= 0; i--) 
{ 
    if (existing.Contains(myList[i])) 
    { 
     myList.RemoveAt(i); 
    } 
    else 
    { 
     existing.Add(myList[i]); 
    } 
} 

Wir zählen rückwärts, ohne einen Iterator zu verwenden (sonst würden Sie Fehler bekommen, wenn Sie die Liste während der Iteration ändern).

HashSet<T> hat auch Überladungen für das Überschreiben der Gleichheit, wenn Sie es brauchen.

Persönlich würde ich für dasblinkenlight's answer für Lesbarkeit gehen.

6

Sie können für diese Zwecke verwenden HashSet (http://msdn.microsoft.com/en-us/library/bb359438.aspx)

class SameTuplesComparer<T1, T2> : EqualityComparer<Tuple<T1, T2>> 
{ 
    public override bool Equals(Tuple<T1, T2> t1, Tuple<T1, T2> t2) 
    { 
     return t1.Item1.Equals(t2.Item1) && t1.Item2.Equals(t2.Item2) 
    } 


    public override int GetHashCode(Tuple<T1, T2> t) 
    { 
    return base.GetHashCode(); 
    } 
} 

Also, wenn Sie Ihre eigenen comparer schreiben, können Sie Strings ein wenig anders vergleichen (wie zB casesensetive nicht):

class SameStringTuplesComparer: EqualityComparer<Tuple<string, string>> 
{ 
    public override bool Equals(Tuple<string, string> t1, Tuple<string, string> t2) 
    { 
     return t1.Item1.Equals(t2.Item1, StringComparison.CurrentCultureIgnoreCase) && t1.Item2.Equals(t2.Item2, StringComparison.CurrentCultureIgnoreCase) 
    } 


    public override int GetHashCode(Tuple<string, string> t) 
    { 
    return base.GetHashCode(); 
    } 
} 

dann in Code:

var hashSet = new HashSet<Tuple<string, string>>(list, new SameTuplesComparer()); 

oder ohne eigene vergleichen r:

var hashSet = HashSet<Tuple<string, string>>(list); 

Jetzt können Sie Elemente zu HashSet hinzufügen und alle Elemente werden eindeutig sein. Nachdem Sie mit dem Hinzufügen von Elementen getan können Sie es konvertieren wieder zur Liste:

var uniquedList = hashSet.ToList(); 

Oder benutzen Sie einfach list.Distinct().ToList()

+0

Beachten Sie, dass Sie in diesem Fall mit einem 'HashSet ' enden und nicht mit einer 'Liste '. Auch ein 'Tuple ' benötigt keinen Vergleichsgenerator. –

+0

Antwort wurde bearbeitet, danke –

+0

+1 Für die extra Alternative. –

Verwandte Themen