Der schnellste Weg, um doppelten Wert von einer Liste <> von Lambda zu entfernen

73

Was ist der schnellste Weg, um doppelte Werte aus einer Liste zu entfernen? Angenommen, List<long> longs = new List<long> { 1, 2, 3, 4, 3, 2, 5 };ich bin daran interessiert, Lambda zu verwenden, um Duplikate zu entfernen und zurückzugeben : {1, 2, 3, 4, 5}. Was ist dein Vorschlag?

Saeid
quelle
5
wie wäre es longs.Distinct()?
Zerkms

Antworten:

131

Der einfachste Weg, eine neue Liste zu erhalten, wäre:

List<long> unique = longs.Distinct().ToList();

Ist das gut genug für Sie oder müssen Sie die vorhandene Liste mutieren ? Letzteres ist deutlich langatmiger.

Beachten Sie, dass die ursprüngliche Reihenfolge Distinct()nicht garantiert erhalten bleibt, in der aktuellen Implementierung jedoch - und das ist die natürlichste Implementierung. Weitere Informationen finden Sie in meinem Edulinq-BlogbeitragDistinct() .

Wenn Sie es nicht brauchen, um ein zu sein List<long>, können Sie es einfach behalten als:

IEnumerable<long> unique = longs.Distinct();

An diesem Punkt wird das De-Duping jedes Mal durchlaufen, wenn Sie es wiederholen unique. Ob das gut ist oder nicht, hängt von Ihren Anforderungen ab.

Jon Skeet
quelle
Danke, also denke ich longs = longs.Distinct().ToList()ist richtig. richtig?
Saeid
2
@Saeid: Solange nichts anderes bereits einen Verweis auf die ursprüngliche Liste hat, sollte das in Ordnung sein. Sie müssen zwischen dem Mutieren der Liste selbst und dem Ändern der Variablen unterscheiden, um auf eine neue Liste zu verweisen (was dieser Code tun wird).
Jon Skeet
Wenn es wichtig ist, dieselbe Liste zu mutieren, können wir nicht einfach sagen:var newTmpList = longs.Distinct().ToList(); longs.Clear(); longs.AddRange(newTmpList);
Jeppe Stig Nielsen
1
@ JeppeStigNielsen: Ja, das ist eine Möglichkeit - aber es ist keine besonders schöne Art, es zu tun ...
Jon Skeet
1
Das hat bei mir funktioniert. Ich bin mein Fall, ich musste die Liste aktualisieren, also habe ich nur folgendes getan: long = long.Distinct().ToList();
Tscott
83

Sie können diese Erweiterungsmethode für Aufzählungen verwenden, die komplexere Typen enthalten:

IEnumerable<Foo> distinctList = sourceList.DistinctBy(x => x.FooName);

public static IEnumerable<TSource> DistinctBy<TSource, TKey>(
    this IEnumerable<TSource> source,
    Func<TSource, TKey> keySelector)
{
    var knownKeys = new HashSet<TKey>();
    return source.Where(element => knownKeys.Add(keySelector(element)));
}
Jon Rea
quelle
6
+1 Ausgezeichnete Antwort - die allumfassenden Antworten sind immer meine Favoriten! Genau das habe ich gesucht. Ich liebe es, wie es immer diese Ungleichheit zwischen Primitiven und komplexen Typen gibt. Es ist fast so schlimm wie eine neue Sprache zu lernen und nur das Beispiel # (*% $ () * @ nutzloses Hallo Welt zu haben! Okay, aus meiner Seifenkiste, tolle Antwort!
Legasthenikeraboko
Ich bevorzuge diese Lösung auch, weil sie ein Lambda als OP verwendet, das im Titel angefordert wird (Anmerkung: Linqs Distinct()nicht), so dass es leicht auf anderen Datentypen verwendet werden kann, ohne dass Equals/ GetHashCodeoder einIEqualityComparer
ZoolWay
Sehr elegante Lösung aber nach? Wir haben eine Quellliste und eine eindeutige Liste. Wie können wir das dbSet aktualisieren, um Änderungen in der Datenbank widerzuspiegeln?
Nolmë Informatique
fantastische Antwort! und du willst durch viele Tasten unterscheiden, ruf es einfach mehrmals mit verschiedenen Schlüsselwählern an :)
Al-Hanash Moataz
7

Es gibt die Distinct () -Methode. es sollte funktionieren.

List<long> longs = new List<long> { 1, 2, 3, 4, 3, 2, 5 };
var distinctList = longs.Distinct().ToList();
Pongsathon.keng
quelle
6

Wenn Sie bei der ursprünglichen Liste bleiben möchten, anstatt eine neue zu erstellen, können Sie etwas Ähnliches Distinct()tun, wie es die Erweiterungsmethode intern tut, dh ein HashSet verwenden, um die Eindeutigkeit zu überprüfen:

HashSet<long> set = new HashSet<long>(longs.Count);
longs.RemoveAll(x => !set.Add(x));

Die List-Klasse bietet diese praktische RemoveAll(predicate)Methode, mit der alle Elemente gelöscht werden, die die vom Prädikat angegebene Bedingung nicht erfüllen. Das Prädikat ist ein Delegat, der einen Parameter des Elementtyps der Liste verwendet und einen Bool-Wert zurückgibt. Die HashSet- Add()Methode gibt nur dann true zurück, wenn das Set das Element noch nicht enthält. Wenn Sie also Elemente aus der Liste entfernen, die nicht zum Satz hinzugefügt werden können, entfernen Sie effektiv alle Duplikate.

Wormbo
quelle
2
List<long> distinctlongs = longs.Distinct().OrderBy(x => x).ToList();
Nikhil Agrawal
quelle
2

Eine einfache intuitive Implementierung

public static List<PointF> RemoveDuplicates(List<PointF> listPoints)
{
    List<PointF> result = new List<PointF>();

    for (int i = 0; i < listPoints.Count; i++)
    {
        if (!result.Contains(listPoints[i]))
            result.Add(listPoints[i]);
    }

    return result;
}
Moctar Haiz
quelle
-2

An Ort und Stelle:

    public static void DistinctValues<T>(List<T> list)
    {
        list.Sort();

        int src = 0;
        int dst = 0;
        while (src < list.Count)
        {
            var val = list[src];
            list[dst] = val;

            ++dst;
            while (++src < list.Count && list[src].Equals(val)) ;
        }
        if (dst < list.Count)
        {
            list.RemoveRange(dst, list.Count - dst);
        }
    }
Const Mi.
quelle