2009-08-01 41 views
28

Ancora imparando Python (finalmente!) E non riesco ancora a riprendermi. Quello che voglio fare è ordinare un dizionario di liste per valore usando il terzo elemento nell'elenco. È abbastanza facile ordinare un dizionario per valore quando il valore è solo un singolo numero o una stringa, ma questa lista mi ha confuso.Python: ordinamento di un dizionario di liste

Esempio:

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

io voglio essere in grado di scorrere attraverso il dizionario in ordine del terzo valore in ogni elenco, in questo caso 9, 3, 11.

Grazie molto per qualsiasi Aiuto!

risposta

33

Ecco un modo per farlo:

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

La key argument della funzione sorted consente di derivare una chiave di ordinamento per ogni elemento della lista.

Per scandire le chiavi/valori in questo elenco, è possibile usare qualcosa come:

>>> 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

Non appena ho posto la domanda ho avuto un'illuminazione e fondamentalmente mi è venuta in mente la stessa cosa tranne che per il lambda (non ho ancora imparato a conoscerli). Ho appena scritto la mia funzione di cmp che accetta tupples da dict.items() e restituisce il risultato. Stessa cosa, solo un modo diverso di scriverlo. Grazie mille per la rapida risposta! – jay

+0

Ottima soluzione. Adoro la semplicità di 'sorted()'. –

+4

Penso che sia un po 'più chiaro in questo modo: ordinato (myDict.items(), key = lambda (k, v): v [2]) –

2

lei ha dichiarato due molto diversa vuole:

  1. "Quello che voglio fare è sorta una Dizionario di liste ..."
  2. 'voglio essere in grado di scorrere il dizionario in ordine di ...'

Il primo di questi è per definizione impossibile: ordinare qualcosa implica un riarrangiamento in un certo ordine. I dizionari Python sono intrinsecamente non ordinati. Il secondo sarebbe vagamente possibile ma estremamente improbabile da implementare.

Che cosa si può fare è

  1. Prendete una copia del contenuto del dizionario (che sarà abbastanza non ordinata)
  2. Ordina che
  3. iterare i risultati ordinati - e già due soluzioni per questo. A proposito, la soluzione che utilizza "chiave" invece di "cmp" è migliore; vedi sorted

"il terzo elemento della lista" puzza "il terzo elemento in una tupla" a me, ed "e [1] [2]" solo gli odori :-) ... come si può investigare usando tuple nominate invece di liste; vedi named tuple factory

Se avete intenzione di fare l'estratto/tipo/processo spesso su grandi insiemi di dati, come si potrebbe prendere in considerazione qualcosa di simile, utilizzando il modulo sqlite3 Python fornito:

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

Come John Machlin ha detto che non puoi effettivamente ordinare un dizionario Python.

Tuttavia, è possibile creare un indice delle chiavi che possono essere ordinate nell'ordine desiderato.

Il pattern Python preferito (idioma) per l'ordinamento da qualsiasi criterio alternativo è chiamato "decorare-ordinamento-undecorate" (DSU). In questo idioma crei un elenco temporaneo che contiene tuple delle tue chiavi seguite dagli elementi di dati originali, quindi chiama il normale metodo .sort() in tale elenco (o, nelle versioni più recenti di Python, semplicemente avvolgi il tuo decorazione in un chiamato alla funzione integrata ordinata()). Quindi rimuovi le "decorazioni".

Il motivo di questo è generalmente preferiti passando funzione di confronto alla .Sort() metodo è che di Python incorporata codice ordinamento predefinito (compilato C nel normale C Python) è molto veloce ed efficiente nel caso di default , ma molto, molto più lentamente quando deve chiamare il codice oggetto Python molte, molte volte nel caso non predefinito. Quindi di solito è molto meglio iterare sui dati che creano strutture di dati che possono essere passate alle routine di ordinamento predefinite.

In questo caso si dovrebbe essere in grado di usare qualcosa come:

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

... che è una lista di comprensione facendo l'undecorate dalla lista ordinata di tuple che viene restituito dalla lista di comprensione interiore. La comprensione interiore sta creando una serie di tuple, la chiave di ordinamento desiderata (il terzo elemento della lista) e la chiave del dizionario corrispondente alla chiave di ordinamento. myDict.keys() è, ovviamente, un metodo di dizionari Python che restituisce un elenco di tutte le chiavi valide in qualsiasi ordine che l'implementazione sottostante sceglie --- presumibilmente una semplice iterazione sugli hash.

Un modo più dettagliato di fare questo potrebbe essere più facile da leggere:

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

Di solito si dovrebbe costruito tale codice in modo iterativo, l'interprete utilizzando piccoli campioni di dati. Costruisci l'espressione o la funzione "decorare". Quindi avvolgere quello in una chiamata a ordinato(). Quindi costruisci l'espressione non decorata (che di solito è tanto semplice quanto quella che ho mostrato qui).

+0

(1) Confrontiamo decor-sort-undecorate con l'uso di cmp arg, l'introduzione della chiave arg ha tagliato una fetta molto ampia del territorio della DSU. (2) La tua soluzione lascia l'OP con un elenco di i tasti dict ... per ottenere ciò che vuole, dovrà fare ancora un altro ciclo degli elementi dict (3) il tuo modo verboso ha un refuso: s/v [2],/v [2], k / –

Problemi correlati