Hat jemand eine schnelle Methode zum Deduplizieren einer generischen Liste in C #?
c#
list
generics
duplicates
JC Grubbs
quelle
quelle
ICollection<MyClass> withoutDuplicates = new HashSet<MyClass>(inputList);
Antworten:
Vielleicht sollten Sie ein HashSet verwenden .
Über den MSDN-Link:
quelle
HashSet
hat keinen Index , daher ist es nicht immer möglich, ihn zu verwenden. Ich muss einmal eine riesige Liste ohne Duplikate erstellen und sie dannListView
im virtuellen Modus verwenden. Es war superschnell,HashSet<>
zuerst eine zu erstellen und sie dann in eine umzuwandelnList<>
(soListView
kann über den Index auf Elemente zugegriffen werden).List<>.Contains()
ist zu langsam.Wenn Sie .Net 3+ verwenden, können Sie Linq verwenden.
quelle
Wie wäre es mit:
In .net 3.5?
quelle
Initialisieren Sie einfach ein HashSet mit einer Liste des gleichen Typs:
Oder wenn Sie eine Liste zurückgeben möchten:
quelle
List<T>
als Ergebnis benötigennew HashSet<T>(withDupes).ToList()
Sortieren Sie es und überprüfen Sie zwei und zwei nebeneinander, da die Duplikate zusammenklumpen.
Etwas wie das:
Anmerkungen:
quelle
RemoveAt
ist eine sehr kostspielige Operation an einemList
Ich benutze gerne diesen Befehl:
Ich habe diese Felder in meiner Liste: ID, Geschäftsname, Stadt, Postleitzahl Ich wollte eine Liste der Städte in einer Dropdown-Liste mit doppelten Werten anzeigen. Lösung: Nach Stadt gruppieren und dann die erste für die Liste auswählen.
Ich hoffe, es hilft :)
quelle
Es hat bei mir funktioniert. einfach benutzen
Ersetzen Sie "Typ" durch Ihren gewünschten Typ, z. B. int.
quelle
Wie kronoz in .Net 3.5 sagte, können Sie verwenden
Distinct()
.In .Net 2 können Sie es nachahmen:
Dies kann zum Deduplizieren einer Sammlung verwendet werden und gibt die Werte in der ursprünglichen Reihenfolge zurück.
Normalerweise ist es viel schneller, eine Sammlung zu filtern (wie beides
Distinct()
und dieses Beispiel), als Elemente daraus zu entfernen.quelle
HashSet
bemerkt, dass der Konstruktor dedupiert hat, was es für die meisten Umstände besser macht. Dies würde jedoch die Sortierreihenfolge beibehalten, was aHashSet
nicht tut.Dictionary<T, object>
stattdessen ersetzen.Contains
mit.ContainsKey
und.Add(item)
mit.Add(item, null)
HashSet
bleibt die Ordnung erhalten, währendDistinct()
dies nicht der Fall ist.Eine Erweiterungsmethode könnte ein guter Weg sein ... so etwas:
Und dann rufen Sie zum Beispiel so an:
quelle
In Java (ich nehme an, C # ist mehr oder weniger identisch):
Wenn Sie die ursprüngliche Liste wirklich mutieren wollten:
Um die Ordnung zu erhalten, ersetzen Sie einfach HashSet durch LinkedHashSet.
quelle
var noDupes = new HashSet<T>(list); list.Clear(); list.AddRange(noDupes);
:)Dies nimmt verschiedene (die Elemente ohne doppelte Elemente) und konvertiert es wieder in eine Liste:
quelle
Hinweis: Diese Lösung erfordert keine Kenntnisse von Linq, abgesehen davon, dass sie vorhanden ist.
Code
Fügen Sie zunächst Folgendes oben in Ihre Klassendatei ein:
Jetzt können Sie Folgendes verwenden, um Duplikate aus einem Objekt mit dem Namen zu entfernen
obj1
:Hinweis: Benennen Sie
obj1
in den Namen Ihres Objekts um.Wie es funktioniert
Der Befehl Union listet jeweils einen Eintrag von zwei Quellobjekten auf. Da obj1 beide Quellobjekte sind, reduziert dies obj1 auf einen von jedem Eintrag.
Das
ToList()
gibt eine neue Liste zurück. Dies ist erforderlich, da Linq-Befehle wieUnion
das Ergebnis als IEnumerable-Ergebnis zurückgeben, anstatt die ursprüngliche Liste zu ändern oder eine neue Liste zurückzugeben.quelle
Als Hilfsmethode (ohne Linq):
quelle
Wenn Sie nicht über die Bestellung kümmern können Sie nur die Einzelteile in einen Schub
HashSet
, wenn Sie tun , um die Bestellung erhalten wollen Sie etwas tun können:Oder der Linq-Weg:
Bearbeiten: Die
HashSet
Methode istO(N)
Zeit undO(N)
Raum beim Sortieren und dann einzigartig zu machen (wie von @ lassevk und anderen vorgeschlagen) istO(N*lgN)
Zeit undO(1)
Raum, daher ist mir (wie auf den ersten Blick) nicht so klar, dass die Sortierweise minderwertig ist (meine Entschuldigung für die vorübergehende Abstimmung ...)quelle
Hier ist eine Erweiterungsmethode zum Entfernen benachbarter Duplikate vor Ort. Rufen Sie zuerst Sort () auf und übergeben Sie denselben IComparer. Dies sollte effizienter sein als die Version von Lasse V. Karlsen, die RemoveAt wiederholt aufruft (was zu mehreren Blockspeicherverschiebungen führt).
quelle
Wenn Sie das MoreLINQ- Paket über Nuget installieren, können Sie die Objektliste leicht anhand einer Eigenschaft unterscheiden
quelle
Es könnte einfacher sein, einfach sicherzustellen, dass der Liste keine Duplikate hinzugefügt werden.
quelle
List<T>.Contains
Methode jedes Mal, aber mit mehr als 1.000.000 Einträgen. Dieser Prozess verlangsamt meine Bewerbung. Ich benutzeList<T>.Distinct().ToList<T>()
stattdessen eine erste.Sie können Union verwenden
quelle
Ein anderer Weg in .Net 2.0
quelle
Es gibt viele Möglichkeiten, das Problem zu lösen. Das Problem mit den Duplikaten in der folgenden Liste ist eine davon:
Prost Ravi Ganesan
quelle
Hier ist eine einfache Lösung, die keinen schwer lesbaren LINQ oder eine vorherige Sortierung der Liste erfordert.
quelle
Die Antwort von David J. ist eine gute Methode, die keine zusätzlichen Objekte, Sortierungen usw. erfordert. Sie kann jedoch verbessert werden:
for (int innerIndex = items.Count - 1; innerIndex > outerIndex ; innerIndex--)
Die äußere Schleife geht also für die gesamte Liste nach oben, die innere Schleife nach unten, "bis die Position der äußeren Schleife erreicht ist".
Die äußere Schleife stellt sicher, dass die gesamte Liste verarbeitet wird, die innere Schleife findet die tatsächlichen Duplikate. Diese können nur in dem Teil auftreten, den die äußere Schleife noch nicht verarbeitet hat.
Oder wenn Sie für die innere Schleife nicht von unten nach oben arbeiten möchten, kann die innere Schleife bei OuterIndex + 1 beginnen.
quelle
Alle Antworten kopieren Listen oder erstellen eine neue Liste oder verwenden langsame Funktionen oder sind nur schmerzhaft langsam.
Nach meinem Verständnis ist dies die schnellste und billigste Methode, die ich kenne (auch unterstützt von einem sehr erfahrenen Programmierer, der auf Echtzeit-Physikoptimierung spezialisiert ist).
Die endgültigen Kosten betragen:
nlogn + n + nlogn = n + 2nlogn = O (nlogn), was ziemlich nett ist.
Hinweis zu RemoveRange: Da wir die Anzahl der Listen nicht festlegen und die Verwendung der Remove-Funktionen vermeiden können, weiß ich nicht genau, wie schnell dieser Vorgang ausgeführt wird, aber ich denke, dies ist der schnellste Weg.
quelle
Wenn Sie zwei Klassen haben
Product
undCustomer
wir doppelte Elemente aus ihrer Liste entfernen möchtenSie müssen eine generische Klasse im folgenden Formular definieren
Anschließend können Sie doppelte Elemente in Ihrer Liste entfernen.
dieser Code entfernen doppelte Elemente durch ,
Id
wenn Sie doppelte Elemente von anderer Eigenschaft wollen entfernen, können Sie ändern ,nameof(YourClass.DuplicateProperty)
gleichennameof(Customer.CustomerName)
dann doppelte Elemente durch Entfernen derCustomerName
Immobilie.quelle
quelle
Eine einfache intuitive Implementierung:
quelle