Ich muss oft ein Wörterbuch, bestehend aus Schlüsseln und Werten, nach Wert sortieren. Zum Beispiel habe ich einen Hash von Wörtern und entsprechenden Frequenzen, die ich nach Häufigkeit ordnen möchte.
Es gibt einen SortedList
Wert für einen einzelnen Wert (z. B. Frequenz), den ich dem Wort wieder zuordnen möchte.
SortedDictionary ordnet nach Schlüssel, nicht nach Wert. Einige greifen auf eine benutzerdefinierte Klasse zurück , aber gibt es einen saubereren Weg?
c#
.net
sorting
dictionary
Kalid
quelle
quelle
IComparer
, das den Trick ausführt (wahr, dass es einen zu vergleichenden Schlüssel akzeptiert, aber mit einem Schlüssel können Sie einen Wert erhalten). ;-)Antworten:
Verwenden:
Da Sie auf .NET 2.0 oder höher abzielen, können Sie dies in Lambda-Syntax vereinfachen - es ist äquivalent, aber kürzer. Wenn Sie auf .NET 2.0 abzielen, können Sie diese Syntax nur verwenden, wenn Sie den Compiler aus Visual Studio 2008 (oder höher) verwenden.
quelle
myList.Sort((x,y)=>x.Value.CompareTo(y.Value));
IEnumerable
, so dass Sie eine sortierte Liste wie diese erhalten können:var mySortedList = myDictionary.OrderBy(d => d.Value).ToList();
Verwenden Sie LINQ:
Dies würde auch eine große Flexibilität ermöglichen, da Sie die Top 10, 20 10% usw. auswählen können. Wenn Sie Ihren Worthäufigkeitsindex für verwenden
type-ahead
, können Sie auch eineStartsWith
Klausel einschließen .quelle
IEnumerable<KeyValuePair<TKey, TValue>>
oder seinOrderedDictionary<TKey, TValue>
. Oder man sollteSortedDictionary
von Anfang an ein verwenden. Für eine Ebene gibtDictionary
die MSDN eindeutig an: "Die Reihenfolge, in der die Artikel zurückgegeben werden, ist undefiniert." Es scheint, dass @ rythos42s neueste Bearbeitung schuld ist. :).ToDictionary
- Standardwörterbücher garantieren keine Sortierreihenfolgequelle
Wenn wir uns umschauen und einige C # 3.0-Funktionen verwenden, können wir dies tun:
Dies ist die sauberste Art, die ich gesehen habe, und ähnelt der Ruby-Methode zum Umgang mit Hashes.
quelle
(for KeyValuePair<string, int> item in keywordCounts.OrderBy(key => key.Value) select item).ToDictionary(t => t.Key, t => t.Value)
- Nur eine kleine Ergänzung zu Ihrer Antwort :) Danke übrigens :)Sie können ein Wörterbuch nach Wert sortieren und in sich selbst speichern (sodass die Werte in der angegebenen Reihenfolge angezeigt werden, wenn Sie darüber nachdenken):
Sicher, es ist vielleicht nicht richtig, aber es funktioniert.
quelle
Auf einer hohen Ebene haben Sie keine andere Wahl, als durch das gesamte Wörterbuch zu gehen und sich jeden Wert anzusehen.
Vielleicht hilft das: http://bytes.com/forum/thread563638.html Kopieren / Einfügen von John Timney:
quelle
Sie würden sowieso nie in der Lage sein, ein Wörterbuch zu sortieren. Sie sind eigentlich nicht bestellt. Die Garantien für ein Wörterbuch bestehen darin, dass die Schlüssel- und Wertsammlungen iterierbar sind und Werte per Index oder Schlüssel abgerufen werden können, es gibt jedoch keine Garantie für eine bestimmte Reihenfolge. Daher müssten Sie das Name-Wert-Paar in eine Liste aufnehmen.
quelle
Sie sortieren keine Einträge im Wörterbuch. Die Wörterbuchklasse in .NET ist als Hashtabelle implementiert - diese Datenstruktur kann per Definition nicht sortiert werden.
Wenn Sie in der Lage sein müssen, Ihre Sammlung (nach Schlüssel) zu durchlaufen, müssen Sie SortedDictionary verwenden, das als binärer Suchbaum implementiert ist.
In Ihrem Fall ist die Quellstruktur jedoch irrelevant, da sie nach einem anderen Feld sortiert ist. Sie müssten es weiterhin nach Häufigkeit sortieren und in eine neue Sammlung einfügen, die nach dem entsprechenden Feld (Häufigkeit) sortiert ist. In dieser Sammlung sind die Frequenzen Schlüssel und Wörter Werte. Da viele Wörter dieselbe Häufigkeit haben können (und Sie sie als Schlüssel verwenden werden), können Sie weder Dictionary noch SortedDictionary verwenden (sie erfordern eindeutige Schlüssel). Dadurch erhalten Sie eine SortedList.
Ich verstehe nicht, warum Sie darauf bestehen, einen Link zum Originalelement in Ihrem Haupt- / Erstwörterbuch beizubehalten.
Wenn die Objekte in Ihrer Sammlung eine komplexere Struktur hätten (mehr Felder) und Sie in der Lage sein müssten, mithilfe mehrerer verschiedener Felder als Schlüssel effizient auf sie zuzugreifen / sie zu sortieren, benötigen Sie wahrscheinlich eine benutzerdefinierte Datenstruktur, die aus dem Hauptspeicher besteht unterstützt das Einfügen und Entfernen von O (1) (LinkedList) und verschiedene Indexierungsstrukturen - Dictionaries / SortedDictionaries / SortedLists. Diese Indizes verwenden eines der Felder aus Ihrer komplexen Klasse als Schlüssel und einen Zeiger / Verweis auf den LinkedListNode in der LinkedList als Wert.
Sie müssten Einfügungen und Entfernungen koordinieren, um Ihre Indizes mit der Hauptsammlung (LinkedList) synchron zu halten, und Entfernungen wären meiner Meinung nach ziemlich teuer. Dies ähnelt der Funktionsweise von Datenbankindizes - sie eignen sich hervorragend für Suchvorgänge, werden jedoch zu einer Belastung, wenn Sie viele Einfügungen und Löschungen durchführen müssen.
All dies ist nur gerechtfertigt, wenn Sie eine nachschlagende Verarbeitung durchführen. Wenn Sie sie nur einmal nach Häufigkeit sortiert ausgeben müssen, können Sie einfach eine Liste von (anonymen) Tupeln erstellen:
quelle
quelle
Oder zum Spaß könnten Sie einige LINQ-Erweiterungsgüte verwenden:
quelle
Sortieren einer
SortedDictionary
Liste zum Binden in einListView
Steuerelement mithilfe von VB.NET:XAML:
quelle
Der einfachste Weg, ein sortiertes Wörterbuch zu erhalten, ist die Verwendung der integrierten
SortedDictionary
Klasse:sortedSections
will enthält die sortierte Version vonsections
quelle
SortedDictionary
sortieren Sie nach Schlüsseln. Das OP möchte nach Wert sortieren.SortedDictionary
hilft in diesem Fall nicht.sorteddictionary()
immer mindestens 1 Mikrosekunde gewonnen, und es ist viel einfacher zu verwalten (da der Aufwand für die Rückkonvertierung in etwas, mit dem man leicht interagieren und es ähnlich wie bei einem Wörterbuch verwalten kann, 0 beträgt (es ist bereits asorteddictionary
)).Die anderen Antworten sind gut, wenn Sie nur eine "temporäre" Liste nach Wert sortieren möchten. Wenn Sie jedoch möchten, dass ein nach
Key
diesem sortiertes Wörterbuch automatisch mit einem anderen nach sortierten Wörterbuch synchronisiert wirdValue
, können Sie dieBijection<K1, K2>
Klasse verwenden .Bijection<K1, K2>
Mit dieser Option können Sie die Sammlung mit zwei vorhandenen Wörterbüchern initialisieren. Wenn Sie also möchten, dass eines davon unsortiert und das andere sortiert wird, können Sie Ihre Bijektion mit Code wie erstellenSie können
dict
wie jedes normale Wörterbuch (das es implementiertIDictionary<K, V>
) verwenden und dann aufrufendict.Inverse
, um das "inverse" Wörterbuch zu erhalten, das nach sortiert istValue
.Bijection<K1, K2>
ist Teil von Loyc.Collections.dll , aber wenn Sie möchten, können Sie den Quellcode einfach in Ihr eigenes Projekt kopieren .Hinweis : Falls es mehrere Schlüssel mit demselben Wert gibt, können Sie diese nicht verwenden
Bijection
, aber Sie können manuell zwischen einem normalenDictionary<Key,Value>
und einem synchronisierenBMultiMap<Value,Key>
.quelle
Angenommen, wir haben ein Wörterbuch als
1) Sie können verwenden
temporary dictionary to store values as
:quelle
Tatsächlich haben Wörterbücher in C # keine sort () -Methoden, da Sie mehr an der Sortierung nach Werten interessiert sind. Sie können keine Werte abrufen, bis Sie ihnen den Schlüssel geben. Kurz gesagt, Sie müssen sie mithilfe von LINQs Order By durchlaufen.
Sie können einen Trick machen,
oder
Es hängt auch davon ab, welche Art von Werten Sie speichern,
ob es sich um einzelne (wie Zeichenfolge, Int) oder mehrere (wie Liste, Array, benutzerdefinierte Klasse) handelt.
Wenn Sie einzelne Werte erstellen können, wenden Sie sort an.
Wenn eine benutzerdefinierte Klasse vorhanden ist, muss diese Klasse IComparable implementieren
ClassName: IComparable<ClassName>
und überschreiben,compareTo(ClassName c)
da sie schneller als LINQ und objektorientierter sind.quelle
Erforderlicher Namespace:
using System.Linq;
Bestellung nach absteigend:
Bestellung von Asc:
quelle
Sie können das Wörterbuch nach Wert sortieren und das Ergebnis im Wörterbuch mit dem folgenden Code abrufen:
quelle
Wenn Sie über ein Wörterbuch verfügen, können Sie diese direkt nach Werten sortieren, indem Sie einen einzigen Liner verwenden:
quelle