2009-08-01 15 views
28

Todavía estoy aprendiendo Python (¡por fin!) Y todavía no puedo entender bien este tema. Lo que quiero hacer es ordenar un diccionario de listas por valor utilizando el tercer elemento de la lista. Es bastante fácil clasificar un diccionario por valor cuando el valor es solo un número o cadena, pero esta cosa de la lista me tiene desconcertado.Python: ordenando un diccionario de listas

Ejemplo:

myDict = { 'item1' : [ 7, 1, 9], 'item2' : [8, 2, 3], 'item3' : [ 9, 3, 11 ] } 

Quiero ser capaz de recorrer el diccionario con el fin del tercer valor en cada lista, en este caso 9, 3, 11.

Gracias mucho para cualquier ¡ayuda!

Respuesta

33

Aquí es una manera de hacer esto:

>>> sorted(myDict.items(), key=lambda e: e[1][2]) 
[('item2', [8, 2, 3]), ('item1', [7, 1, 9]), ('item3', [9, 3, 11])] 

El key argument de la función sorted le permite derivar una clave de clasificación para cada elemento de la lista.

para repetir las llaves/valores de esta lista, puede usar algo como:

>>> for key, value in sorted(myDict.items(), key=lambda e: e[1][2]): 
... print key, value 
... 
item2 [8, 2, 3] 
item1 [7, 1, 9] 
item3 [9, 3, 11] 
+1

Tan pronto como hice la pregunta tuve una epifanía y, básicamente, se me ocurrió lo mismo a excepción de la lambda (no he aprendido aún sobre ellos). Acabo de escribir mi propia función cmp que toma tupples de dict.items() y devuelve el resultado. Lo mismo, simplemente una forma diferente de escribirlo. Muchas gracias por la respuesta rápida! – jay

+0

Gran solución. Me encanta la simplicidad de 'sorted()'. –

+4

Creo que es un poco más claro de esta manera: ordenado (myDict.items(), clave = lambda (k, v): v [2]) –

2

Usted ha declarado dos bastante diferente quiere:

  1. "Lo que quiero hacer es ordenar una diccionario de listas ..."
  2. 'quiero ser capaz de recorrer el diccionario con el fin de ...'

El primero de ellos es, por definición, imposible: ordenar algo implica una reorganización en algún orden. Los diccionarios de Python están inherentemente desordenados. El segundo sería vagamente posible pero muy poco probable que se implemente.

Lo que puede hacer es

  1. Tome una copia de los contenidos del diccionario (que será bastante desordenada )
  2. Ordenar que
  3. iterar sobre los resultados ordenados - y ya tienen dos soluciones para eso. Por cierto, la solución que usa "clave" en su lugar de "cmp" es mejor; ver sorted

"el tercer elemento de la lista" huele "el tercer elemento de una tupla" para mí, y "e [1] [2]" huele ... :-) que le gusten para investigar el uso de tuplas con nombre en lugar de listas; ver named tuple factory

Si usted va a estar haciendo extracto/tipo/proceso a menudo en grandes conjuntos de datos, es posible que desee considerar algo como esto, utilizando el módulo del sqlite3 suministrado en Python:

create table ex_dict (k text primary key, v0 int, v1 int, v2 int); 
insert into ex_dict values('item1', 7, 1, 9); 
-- etc etc 
select * from ex_dict order by v2; 
2

Como Juan Machlin dijo que en realidad no se puede ordenar un diccionario de Python.

Sin embargo, puede crear un índice de las teclas que se pueden ordenar en el orden que desee.

El patrón Python (idioma) preferido para la clasificación por cualquier criterio alternativo se llama "decorate-sort-undecorate" (DSU). En este idioma, usted crea una lista temporal que contiene tuplas de sus claves seguidas por sus elementos de datos originales, luego llame al método normal .sort() en esa lista (o, en versiones más recientes de Python simplemente envuelva su decoración en una llamada a la ordenada() función incorporada). Luego eliminas las "decoraciones".

La razón de esto es generalmente preferible a pasar función de comparación a la .Sort() método es que Python integrado de códigos de clasificación por defecto (C compilado en el C normal de Python) es muy rápido y eficiente en el caso por defecto , pero mucho, mucho más lento cuando tiene que llamar al código objeto Python muchas, muchas veces en el caso no predeterminado. Por lo tanto, generalmente es mejor iterar sobre las estructuras de datos de creación de datos que se pueden pasar a las rutinas de clasificación predeterminadas.

En este caso, debería ser capaz de usar algo como:

[y[1] for y in sorted([(myDict[x][2], x) for x in myDict.keys()])] 

... eso es una lista por comprensión haciendo el Undecorate de la lista ordenada de tuplas que está siendo devuelto por la lista por comprensión interior. La comprensión interna está creando un conjunto de tuplas, la tecla de clasificación deseada (el tercer elemento de la lista) y la tecla del diccionario correspondiente a la tecla de clasificación. myDict.keys() es, por supuesto, un método de diccionarios de Python que devuelve una lista de todas las claves válidas en el orden que elija la implementación subyacente, presumiblemente una iteración simple sobre los hash.

Un modo más detallado de lo contrario, podría ser más fácil de leer:

temp = list() 
for k, v in myDict.items(): 
    temp.append((v[2],)) 
temp.sort() 
results = list() 
for i in temp: 
    results.append(i[1]) 

lo general, se debería construido dicho código de forma iterativa, en el intérprete usando pequeñas muestras de datos. Desarrolle la expresión o función "decorar". Luego envuelva eso en una llamada al ordenado(). Luego compila la expresión undecorate (que generalmente es tan simple como lo que he mostrado aquí).

+0

(1) Se compara decorate-sort-undecorate con el uso de cmp arg; introducción de la clave arg cortada de una porción muy grande del territorio de DSU. (2) Su solución deja el OP con una lista de las claves dict ... para obtener lo que quiere, tendrá que hacer otro ciclo más de los ítems dict (3) tu forma verbosa tiene un error tipográfico: s/v [2],/v [2], k / –

Cuestiones relacionadas