Ich habe 60.000 Elemente, die mit einer 20.000 Suchliste verglichen werden müssen. Gibt es eine Sammelobjekt (wie List
, HashTable
) , die eine exceptionly schnell liefert Contains()
Methode? Oder muss ich meine eigenen schreiben? Mit anderen Worten, ist die Standardmethode Contains()
, dass nur jedes Element gescannt wird oder ein besserer Suchalgorithmus verwendet wird.
foreach (Record item in LargeCollection)
{
if (LookupCollection.Contains(item.Key))
{
// Do something
}
}
Hinweis . Die Suchliste ist bereits sortiert.
c#
.net
search
collections
Ondrej Janacek
quelle
quelle
Antworten:
Betrachten
System.Collections.Generic.HashSet
Sie im allgemeinsten Fall Ihre Standarddatenstruktur "Enthält" als Arbeitspferd, da die Auswertung eine konstante Zeit in Anspruch nimmtContains
.Die tatsächliche Antwort auf "Was ist die am schnellsten durchsuchbare Sammlung" hängt von Ihrer spezifischen Datengröße, Reihenfolge, Hashing-Kosten und Suchhäufigkeit ab.
quelle
Wenn Sie keine Bestellung benötigen, versuchen Sie es
HashSet<Record>
(neu in .Net 3.5)Wenn Sie dies tun, verwenden Sie a
List<Record>
und rufen Sie anBinarySearch
.quelle
ImmutableSortedSet
von System.ImmutableCollectionsHast du darüber nachgedacht?
List.BinarySearch(item)
?Sie sagten, dass Ihre große Sammlung bereits sortiert ist, sodass dies die perfekte Gelegenheit zu sein scheint? Ein Hash wäre definitiv der schnellste, aber dies bringt seine eigenen Probleme mit sich und erfordert viel mehr Overhead für die Speicherung.
quelle
Sie sollten diesen Blog lesen , in dem die Geschwindigkeit verschiedene Arten von Sammlungen und Methoden für jede mit Einzel- und Multithread-Techniken getestet hat.
Den Ergebnissen zufolge waren BinarySearch on a List und SortedList die Top-Performer, die ständig Hals in Hals liefen, wenn sie etwas als "Wert" suchten.
Bei Verwendung einer Sammlung, die "Schlüssel" zulässt, schnitten Dictionary, ConcurrentDictionary, Hashset und HashTables insgesamt am besten ab.
quelle
Halten Sie beide Listen x und y in sortierter Reihenfolge.
Wenn x = y, führen Sie Ihre Aktion aus, wenn x <y, x vorrücken, wenn y <x, y vorrücken, bis eine der Listen leer ist.
Die Laufzeit dieser Kreuzung ist proportional zu min (Größe (x), Größe (y))
Führen Sie keine .Contains () -Schleife aus, diese ist proportional zu x * y, was viel schlimmer ist.
quelle
Wenn es möglich ist, Ihre Artikel zu sortieren, gibt es eine viel schnellere Möglichkeit, dies zu tun, als Schlüsselsuchen in einer Hashtabelle oder einem B-Baum durchzuführen. Wenn Ihre Elemente nicht sortierbar sind, können Sie sie ohnehin nicht wirklich in einen B-Baum einfügen.
Wenn beide Listen sortierbar sind, müssen Sie nur die Suchliste der Reihe nach durchsuchen.
quelle
Wenn Sie .Net 3.5 verwenden, können Sie saubereren Code erstellen, indem Sie:
Ich habe hier kein .Net 3.5 und das ist ungetestet. Es basiert auf einer Erweiterungsmethode. Nicht, dass
LookupCollection.Intersect(LargeCollection)
das wahrscheinlich nicht dasselbe ist wieLargeCollection.Intersect(LookupCollection)
... Letzteres ist wahrscheinlich viel langsamer.Dies setzt voraus, dass LookupCollection a ist
HashSet
quelle
Wenn Sie sich keine Sorgen darüber machen, jedes einzelne Stück Leistung zu quietschen, ist der Vorschlag, ein HashSet oder eine binäre Suche zu verwenden, solide. Ihre Datensätze sind einfach nicht groß genug, damit dies in 99% der Fälle ein Problem darstellt.
Aber wenn dies nur eines von Tausenden von Malen ist und die Leistung kritisch ist (und sich mit HashSet / Binärsuche als inakzeptabel erwiesen hat), können Sie sicherlich Ihren eigenen Algorithmus schreiben, der die sortierten Listen durchläuft und dabei Vergleiche durchführt. Jede Liste würde höchstens einmal durchlaufen und wäre in den pathologischen Fällen nicht schlecht (wenn Sie diese Route einmal gegangen wären, würden Sie wahrscheinlich feststellen, dass der Vergleich, vorausgesetzt, es handelt sich um eine Zeichenfolge oder einen anderen nicht integralen Wert, die tatsächlichen Kosten und diese Optimierung wäre der nächste Schritt).
quelle