2010-04-24 12 views
57

Ho un dizionario in C# comeordinamento di un dizionario in atto per quanto riguarda le chiavi

Dictionary<Person, int> 

e voglio ordinare quel dizionario in atto rispetto ai tasti (un campo in classe Person). Come posso farlo? Ogni aiuto disponibile su Internet è quello delle liste senza un particolare esempio di ordinamento sul posto del dizionario. Qualsiasi aiuto sarebbe molto apprezzato!

+0

Non sono sicuro di aver capito la tua domanda, in quanto un dizionario non è elencato in alcun ordine? Puoi scorrere le chiavi, o i valori, che puoi facilmente ordinare al volo ... –

risposta

116

Non è possibile ordinare un Dictionary<TKey, TValue> - è intrinsecamente non ordinato. (O meglio, l'ordine in cui vengono recuperati iscrizioni è specifico dell'implementazione. Si consiglia di non fare affidamento su di esso di lavoro nello stesso modo tra le versioni, come l'ordinazione non fa parte della sua funzionalità progettate.)

È possibile utilizzare SortedList<TKey, TValue> o SortedDictionary<TKey, TValue>, entrambi ordinati per chiave (in modo configurabile, se si passa un IEqualityComparer<T> nel costruttore) - potrebbero essere utili?

Prestare poca attenzione alla parola "elenco" nel nome SortedList - è ancora un dizionario in quanto associa le chiavi ai valori. È implementato utilizzando internamente una lista, in modo efficace - così, invece di cercare con il codice hash, esegue una ricerca binaria. SortedDictionary si basa similmente su ricerche binarie, ma tramite un albero invece di una lista.

+2

Stai attento a usare 'SortedList ', tuttavia: sarà molto lento se crei un elenco di grandi dimensioni (supponendo che gli elementi siano non pre-ordinato). Di solito dovresti usare 'SortedDictionary ', oppure usare la parte di terzi ['BDictionary '] (http://loyc.net/doc/code/classLoyc_1_1Collections_1_1BDictionary_3_01K_00_01V_01_4.html) per ottenere prestazioni simili a 'SortedDictionary' senza perdere il possibilità di accedere agli articoli per indice o "trova la chiave più vicina". – Qwertie

6

In base alla progettazione, i dizionari non sono ordinabili. Se hai bisogno di questa capacità in un dizionario, guarda invece SortedDictionary.

4

Date un'occhiata a SortedDictionary, c'è anche un sovraccarico di costruttore in modo da poter passare il proprio IComparable per i confronti.

4

La risposta corretta è già stata stabilita (basta usare SortedDictionary).

Tuttavia, se per caso è necessario conservare la raccolta come dizionario, è possibile accedere alle chiavi del dizionario in modo ordinato, ad esempio ordinando le chiavi in ​​un elenco, quindi utilizzando questo elenco per accedi al Dizionario. Un esempio ...

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

... un po 'di codice che riempie "dupcheck", quindi ...

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

Non dimenticare using System.Linq; per questo.

1

Mentre Dizionario è implementato come tabella hash, SortedDictionary è implementato come un albero rosso-nero.

Se non si utilizza l'ordine nell'algoritmo e si devono solo ordinare i dati prima dell'output, utilizzando SortedDictionary avrà un impatto negativo sulle prestazioni.

È possibile "sort" il dizionario come questo:

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

A causa di questo risponde elevata immissione di ricerca ho pensato che il soluzione LINQ OrderBy è la pena che mostra:

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

uscita:

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 questo esempio sarebbe senso utilizzare anche ThenBy per Nomi:

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

L'uscita è:

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 ha anche la OrderByDescending e ThenByDescending per coloro che ne hanno bisogno.

Problemi correlati