Entfernen sequenzieller wiederkehrender Elemente aus ListT mit linq

7

Ich suche nach einer Möglichkeit, die Wiederholung von Elementen in einer Liste zu verhindern, aber die Reihenfolge beizubehalten. Zum Beispiel

%Vor%

sollte

werden %Vor%

Ich habe es ziemlich unelegant mit einer for Schleife gemacht, indem ich das nächste Element wie folgt überprüft habe

%Vor%

Gibt es einen eleganteren Weg dies zu tun, vorzugsweise mit LINQ?

    
Ed W 01.08.2013, 07:40
quelle

9 Antworten

9

Sie können eine Erweiterungsmethode erstellen:

%Vor%

Verwendung:

%Vor%     
Sergey Berezovskiy 01.08.2013 07:48
quelle
4

Du könntest einfach LINQ schreiben:

%Vor%

oder Pythonic (gut, mein bester Versuch) Weg:

%Vor%

Der einfachste ( bearbeiten: hat nicht gesehen, dass es bereits von King King )

%Vor%     
Roman Pekar 01.08.2013 08:28
quelle
3

Sie können auch pure LINQ verwenden:

%Vor%     
King King 01.08.2013 07:58
quelle
2

Wenn Sie eine LINQ-Anweisung wünschen, die nicht auf den erfassten Wert des Ergebnisses innerhalb des Aufrufs angewiesen ist, benötigen Sie ein Konstrukt mit Aggregat, da es die einzige Methode ist, die zusammen mit der Operation einen Wert liefert. I.e. basierend auf Zaheer Ahmeds Code:

%Vor%

Oder Sie können sogar versuchen, eine Liste ohne if :

zu erstellen %Vor%

Hinweis: Um eine angemessene Leistung der obigen Beispiele mit Aggregate zu erhalten, müssten Sie auch den letzten Wert tragen ( Last muss die gesamte Sequenz in jedem Schritt durchlaufen), aber Code, der 3 Werte {IsEmpty, LastValue, Sequence} in a enthält Tuple ist sehr seltsam aussehend. Diese Beispiele dienen nur Unterhaltungszwecken.

Eine weitere Option ist, dass Zip array mit sich selbst um 1 verschoben wird und Elemente zurückgibt, die nicht gleich sind ...

Eine praktikablere Option besteht darin, einen Iterator zu erstellen, der Werte filtert:

%Vor%     
Alexei Levenkov 01.08.2013 07:57
quelle
2

Wenn du wirklich die Welt hasst, pure LINQ:

%Vor%

Beachten Sie jedoch, dass Sie (mindestens teilweise) das Aufzählungszeichen 3 (der Take , der "linke" Teil von Zip , die ersten Parameter von Zip ) aufzählen müssen. Diese Methode ist langsamer als das Erstellen einer yield -Methode oder das direkte Ausführen .

Erläuterung:

  • Sie nehmen die erste Zahl ( .Take(1) )
  • Sie nehmen alle Zahlen von der zweiten ( .Skip(1) ) und paaren sie mit allen Zahlen ( .Zip(nmbs ). Wir nennen curr die Zahlen aus der ersten "Sammlung" und prev die Zahlen aus der zweiten "Sammlung" ( (p, q) => new { prev = q, curr = p }) ). Sie nehmen dann nur die Zahlen, die sich von der vorherigen Zahl unterscheiden ( .Where(p => p.prev != p.curr) ) und von diesen nehmen Sie den curr -Wert und verwerfen den prev -Wert ( .Select(p => p.curr) )
  • Sie erfassen diese beiden Sammlungen ( .Concat( )
xanatos 01.08.2013 08:59
quelle
2

Hier der Code, den Sie brauchen:

%Vor%

Die LINQ Magie ist:

%Vor%

Oder Sie können eine Erweiterungsmethode wie folgt erstellen:

%Vor%     
One Man Crew 01.08.2013 08:03
quelle
1

Versuchen Sie Folgendes:

%Vor%     
Alex Filipovici 01.08.2013 07:54
quelle
1

Überprüfen Sie, ob der letzte der neuen Liste und der aktuelle Eintrag nicht gleich sind, und fügen Sie ihn zu der neuen Liste hinzu:

%Vor%

oder LINQ:

%Vor%

Habe eine korrekte Validierung für das Null-Objekt.

    
Zaheer Ahmed 01.08.2013 07:43
quelle
0

Wenn Sie gerne ein F # -Projekt referenzieren möchten, können Sie

schreiben %Vor%     
Dax Fohl 30.08.2014 15:13
quelle

Tags und Links