Ich habe ein Wörterbuch in C # wie
Dictionary<Person, int>
und ich möchte dieses Wörterbuch in Bezug auf Schlüssel sortieren (ein Feld in der Klasse Person). Wie kann ich es tun? Jede im Internet verfügbare Hilfe ist die von Listen ohne spezielles Beispiel für die Sortierung des Wörterbuchs. Jede Hilfe wäre sehr dankbar!
c#
sorting
dictionary
SoulReaver
quelle
quelle
Antworten:
Sie können a nicht sortieren
Dictionary<TKey, TValue>
- es ist von Natur aus ungeordnet. (Oder besser gesagt, die Reihenfolge, in der Einträge abgerufen werden, ist implementierungsspezifisch. Sie sollten sich nicht darauf verlassen, dass es zwischen den Versionen auf die gleiche Weise funktioniert, da die Reihenfolge nicht Teil der entworfenen Funktionalität ist.)Sie können verwenden
SortedList<TKey, TValue>
oderSortedDictionary<TKey, TValue>
beide nach Schlüssel sortieren (auf konfigurierbare Weise, wenn Sie eineIEqualityComparer<T>
an den Konstruktor übergeben) - könnten diese für Sie von Nutzen sein?Achten Sie wenig auf das Wort "Liste" im Namen
SortedList
- es ist immer noch ein Wörterbuch, da es Schlüssel Werten zuordnet. Es wird mithilfe einer Liste intern und effektiv implementiert. Anstatt nach Hash-Code zu suchen, wird eine binäre Suche durchgeführt.SortedDictionary
basiert ebenfalls auf binären Suchen, jedoch über einen Baum anstelle einer Liste.quelle
SortedList<K,V>
: Es wird sehr langsam sein, wenn Sie eine große Liste erstellen (vorausgesetzt, die Elemente sind nicht vorsortiert). Normalerweise sollten SieSortedDictionary<K,V>
stattdessen oder einen Drittanbieter verwendenBDictionary<K,V>
, um eine ähnliche Leistung zu erzielen,SortedDictionary
ohne die Möglichkeit zu verlieren, über den Index oder "nächstgelegenen Schlüssel suchen" auf Elemente zuzugreifen.SortedList
undSortedDictionary
tatsächlich die falschen Werkzeuge sind, richtig? Das heißt, was ist, wenn ich buchstäblich zu sortieren nur die Wörterbuch will Schlüssel vorhanden?var array = dict.Keys.ToArray(); array.Sort();
Versuchen Sie es mit SortedDictionary
quelle
Die richtige Antwort ist bereits angegeben (verwenden Sie einfach SortedDictionary).
Wenn Sie jedoch zufällig Ihre Sammlung als Wörterbuch behalten müssen, können Sie auf geordnete Weise auf die Wörterbuchschlüssel zugreifen, indem Sie beispielsweise die Schlüssel in einer Liste bestellen und dann über diese Liste auf das Wörterbuch zugreifen. Ein Beispiel...
Dictionary<string, int> dupcheck = new Dictionary<string, int>();
... ein Code, der "dupcheck" ausfüllt, dann ...
if (dupcheck.Count > 0) { Console.WriteLine("\ndupcheck (count: {0})\n----", dupcheck.Count); var keys_sorted = dupcheck.Keys.ToList(); keys_sorted.Sort(); foreach (var k in keys_sorted) { Console.WriteLine("{0} = {1}", k, dupcheck[k]); } }
Vergiss das nicht
using System.Linq;
.quelle
var keys_sorted = dupcheck.Keys.ToList(); keys_sorted.Sort();
- einfacher istkeys_sorted = dupcheck.Keys.OrderBy(k => k).ToList();
... und wenn Sie die Werte verwenden wollen, dann nurforeach (var ent in dupcheck.OrderBy(kv => kv.Key)) Console.WriteLine($"{ent.Key} = {ent.Value}");
Wörterbücher sind von Natur aus nicht sortierbar. Wenn Sie diese Funktion in einem Wörterbuch benötigen, schauen Sie sich stattdessen SortedDictionary an.
quelle
Schauen Sie sich an
SortedDictionary
, es gibt sogar eine Konstruktorüberladung, sodass Sie Ihr eigenes IComparable für die Vergleiche übergeben können.quelle
Während Dictionary als Hash-Tabelle implementiert ist, ist SortedDictionary als Rot-Schwarz-Baum implementiert.
Wenn Sie die Reihenfolge in Ihrem Algorithmus nicht nutzen und die Daten nur vor der Ausgabe sortieren müssen , wirkt sich die Verwendung von SortedDictionary negativ auf die Leistung aus .
Sie können das Wörterbuch folgendermaßen "sortieren":
Dictionary<string, int> dictionary = new Dictionary<string, int>(); // algorithm return new SortedDictionary<string, int>(dictionary);
quelle
dictionary.OrderBy(kv => kv.Key)
Aufgrund dieser hohen Suchposition fand ich, dass die LINQ OrderBy- Lösung es wert ist, gezeigt zu werden:
class Person { public Person(string firstname, string lastname) { FirstName = firstname; LastName = lastname; } public string FirstName { get; set; } public string LastName { get; set; } } static void Main(string[] args) { Dictionary<Person, int> People = new Dictionary<Person, int>(); People.Add(new Person("John", "Doe"), 1); People.Add(new Person("Mary", "Poe"), 2); People.Add(new Person("Richard", "Roe"), 3); People.Add(new Person("Anne", "Roe"), 4); People.Add(new Person("Mark", "Moe"), 5); People.Add(new Person("Larry", "Loe"), 6); People.Add(new Person("Jane", "Doe"), 7); foreach (KeyValuePair<Person, int> person in People.OrderBy(i => i.Key.LastName)) { Debug.WriteLine(person.Key.LastName + ", " + person.Key.FirstName + " - Id: " + person.Value.ToString()); } }
Ausgabe:
Doe, John - Id: 1 Doe, Jane - Id: 7 Loe, Larry - Id: 6 Moe, Mark - Id: 5 Poe, Mary - Id: 2 Roe, Richard - Id: 3 Roe, Anne - Id: 4
In diesem Beispiel wäre es sinnvoll, ThenBy auch für Vornamen zu verwenden:
foreach (KeyValuePair<Person, int> person in People.OrderBy(i => i.Key.LastName).ThenBy(i => i.Key.FirstName))
Dann ist die Ausgabe:
Doe, Jane - Id: 7 Doe, John - Id: 1 Loe, Larry - Id: 6 Moe, Mark - Id: 5 Poe, Mary - Id: 2 Roe, Anne - Id: 4 Roe, Richard - Id: 3
LINQ hat auch OrderByDescending und ThenByDescending für diejenigen, die es benötigen.
quelle