2010-04-24 5 views
57

Ich habe ein Wörterbuch in C# wieein Wörterbuch an Ort und Stelle in Bezug auf Schlüssel Sortierung

Dictionary<Person, int> 

und ich mag, dass Wörterbuch an seinem Platz sortieren in Bezug auf Schlüssel (ein Feld in der Klasse Person). Wie kann ich es tun? Jede verfügbare Hilfe im Internet ist die von Listen ohne spezielles Beispiel für die Sortierung von Dictionary. Jede Hilfe würde sehr geschätzt werden!

+0

Ich bin mir nicht sicher, ob ich Ihre Frage verstehe, da ein Wörterbuch in keiner Reihenfolge aufgezählt wird? Sie durchlaufen entweder die Schlüssel oder die Werte, die Sie im Handumdrehen sortieren können ... –

Antwort

116

Sie können Dictionary<TKey, TValue> nicht sortieren - es ist inhärent ungeordnet. (Oder besser gesagt, die Reihenfolge, in der die Einträge abgerufen werden, ist implementierungsspezifisch. Sie sollten nicht darauf vertrauen, dass es zwischen den Versionen gleich funktioniert, da die Bestellung nicht Teil der entworfenen Funktionalität ist.)

Sie können can Verwenden Sie SortedList<TKey, TValue> oder SortedDictionary<TKey, TValue>, die beide nach dem Schlüssel sortieren (auf konfigurierbare Weise, wenn Sie einen IEqualityComparer<T> im Konstruktor übergeben) - könnten diese für Sie nützlich sein?

Achten Sie auf das Wort "list" im Namen SortedList - es ist immer noch ein Wörterbuch, in dem Schlüssel auf Werte zugeordnet werden. Es ist implementiert mit einer Liste intern, effektiv - so anstelle von Hash-Code nachschlagen, es tut eine binäre Suche. SortedDictionary basiert ähnlich auf binären Suchen, aber über einen Baum anstelle einer Liste.

+2

Seien Sie vorsichtig bei der Verwendung von 'SortedList ', obwohl: es wird sehr langsam sein, wenn Sie eine große Liste erstellen (vorausgesetzt, die Elemente sind nicht vorsortiert). Normalerweise sollten Sie 'SortedDictionary ' statt dessen verwenden, oder verwenden Sie das Third-Party ['BDictionary '] (http://loyc.net/doc/code/classLoyc_1_1Collections_1_1BDictionary_3_01K_00_01V_01_4.html) um eine Leistung ähnlich wie 'SortedDictionary' zu erhalten, ohne die Fähigkeit, auf Einträge per Index oder "Finde den nächsten Schlüssel" zuzugreifen. – Qwertie

6

Die Wörterbücher sind per Entwurf nicht sortierbar. Wenn Sie diese Funktion in einem Wörterbuch benötigen, sehen Sie stattdessen SortedDictionary.

4

Werfen Sie einen Blick auf SortedDictionary, es gibt sogar einen Konstruktor Überlastung, so dass Sie in Ihrem eigenen IComparable für die Vergleiche passieren kann.

4

Die richtige Antwort ist bereits angegeben (verwenden Sie einfach SortedDictionary).

Wenn Sie jedoch Ihre Sammlung als Dictionary behalten möchten, können Sie die Dictionary-Schlüssel geordnet aufrufen, indem Sie z. B. die Schlüssel in einer Liste bestellen und diese Liste dann verwenden Greife auf das Wörterbuch zu. Ein Beispiel ...

Dictionary<string, int> dupcheck = new Dictionary<string, int>(); 

... einige Code, der dann in "dupcheck" füllt ...

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]); 
    } 
} 

Vergessen Sie nicht, using System.Linq; dafür.

1

Während Dictionary als Hash-Tabelle implementiert ist, wird SortedDictionary als Rot-Schwarz-Struktur implementiert.

Wenn Sie die Reihenfolge in Ihrem Algorithmus nicht nutzen und nur die Daten vor der Ausgabe sortieren müssen, hätte mit SortedDictionary negative Auswirkungen auf die Leistung.

Sie können "sort" das Wörterbuch wie folgt aus:

Dictionary<string, int> dictionary = new Dictionary<string, int>(); 
// algorithm 
return new SortedDictionary<string, int>(dictionary); 
0

Aufgrund dieser Antworten hohe Such Platzierung Ich dachte, die LINQ SortiertNach Lösung lohnt sich zeigt:

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()); 
    } 
} 

Ausgang:

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ürde es auch ThenBy sinnvoll verwenden für Vornamen:

foreach (KeyValuePair<Person, int> person in People.OrderBy(i => i.Key.LastName).ThenBy(i => i.Key.FirstName)) 

Dann ist der Ausgang ist:

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 die OrderByDescending und ThenByDescending für diejenigen, die es brauchen.

Verwandte Themen