2010-04-24 6 views
57

que tienen un diccionario en C# comoOrdenar un diccionario en su lugar con respecto a las claves

Dictionary<Person, int> 

y quiero ordenar ese diccionario en su lugar con respecto a las teclas (un campo en la clase de persona). ¿Cómo puedo hacerlo? Toda la ayuda disponible en Internet es la de listas sin ningún ejemplo particular de ordenación in situ de Diccionario. ¡Cualquier ayuda sería muy apreciada!

+0

No estoy seguro de entender su pregunta, ya que un diccionario no está enumerado en ningún orden? O bien iterar a través de las teclas, o los valores, que puede ordenar fácilmente sobre la marcha ... –

Respuesta

116

No se puede ordenar un Dictionary<TKey, TValue> - está inherentemente desordenado. (O mejor dicho, el orden en el que se recuperan las entradas es específico de la implementación. Usted no debe confiar en que funcione de la misma manera entre las versiones, como la solicitud no es parte de su funcionalidad diseñada.)

Usted puede use SortedList<TKey, TValue> o SortedDictionary<TKey, TValue>, ambos clasificados por la clave (de forma configurable, si pasa un IEqualityComparer<T> en el constructor) - ¿podrían serle de utilidad?

Preste poca atención a la palabra "lista" en el nombre SortedList - sigue siendo un diccionario en que mapea las claves de los valores. Es implementado usando una lista internamente, de manera efectiva, por lo que en lugar de buscar por código hash, realiza una búsqueda binaria. SortedDictionary se basa de manera similar en búsquedas binarias, pero a través de un árbol en lugar de una lista.

+2

Tenga cuidado al usar 'SortedList ', aunque: será muy lento si construye una lista grande (suponiendo que los elementos son no pre-clasificado). Por lo general, debe utilizar 'SortedDictionary ' en su lugar, o utilizar el tercero ['BDictionary '] (http://loyc.net/doc/code/classLoyc_1_1Collections_1_1BDictionary_3_01K_00_01V_01_4.html) para obtener un rendimiento similar al de 'SortedDictionary' sin perder el capacidad de acceder a los elementos por índice o "encontrar la clave más cercana". – Qwertie

6

Por diseño, los diccionarios no se pueden ordenar. Si necesita esta capacidad en un diccionario, consulte SortedDictionary en su lugar.

4

Tome un vistazo a SortedDictionary, incluso hay una sobrecarga de constructor de lo que puede pasar en su propia IComparable para las comparaciones.

4

La respuesta correcta ya está establecida (solo use SortedDictionary).

Sin embargo, si por casualidad necesita mantener su colección como Diccionario, es posible acceder a las claves del Diccionario de una manera ordenada, por ejemplo, ordenando las claves en una Lista, luego usando esta lista para acceder al Diccionario. Un ejemplo ...

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

... un código que rellena "dupcheck", entonces ...

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

No olvide using System.Linq; para esto.

1

Mientras que el diccionario se implementa como una tabla hash, SortedDictionary se implementa como un árbol rojo-negro.

Si no aprovecha el orden de su algoritmo y solo necesita ordenar los datos antes de la salida, utilizando SortedDictionary tendrá un impacto negativo en el rendimiento de.

Puede "tipo" del diccionario de la siguiente manera:

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

Debido a esto responde a alta colocación de búsqueda pensé que la solución LINQ OrdenarPor es digno de mostrar:

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

Salida:

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 

En este ejemplo, lo haría tiene sentido utilizar también ThenBy por primer nombre:

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

entonces la salida es:

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 también tiene la OrderByDescending y ThenByDescending para aquellos que lo necesitan.

Cuestiones relacionadas