[python] Come si ordina un dizionario in base al valore?



14 Answers

Semplice come: sorted(dict1, key=dict1.get)

Bene, in realtà è possibile fare un "ordinamento per valori di dizionario". Recentemente ho dovuto farlo in un Code Golf (Stack Overflow question Code golf: Word frequency chart ). Ridotto, il problema era del tipo: dato un testo, conta quante volte ogni parola viene incontrata e mostra un elenco delle parole migliori, ordinate per frequenza decrescente.

Se costruisci un dizionario con le parole come chiavi e il numero di occorrenze di ogni parola come valore, qui semplificato come:

from collections import defaultdict
d = defaultdict(int)
for w in text.split():
  d[w] += 1

quindi è possibile ottenere un elenco delle parole, ordinate per frequenza di utilizzo con sorted(d, key=d.get) - l'ordinamento itera sulle chiavi del dizionario, utilizzando il numero di occorrenze di parole come chiave di ordinamento.

for w in sorted(d, key=d.get, reverse=True):
  print w, d[w]

Sto scrivendo questa spiegazione dettagliata per illustrare ciò che le persone spesso intendono con "Posso facilmente ordinare un dizionario per chiave, ma come faccio a ordinare per valore" - e penso che l'OP stia cercando di risolvere un problema del genere. E la soluzione è fare una sorta di elenco delle chiavi, in base ai valori, come mostrato sopra.

Question

Ho un dizionario di valori letti da due campi in un database: un campo stringa e un campo numerico. Il campo stringa è unico, quindi è la chiave del dizionario.

Posso ordinare i tasti, ma come posso ordinare in base ai valori?

Nota: ho letto question Come faccio a ordinare una lista di dizionari in base ai valori del dizionario in Python? e probabilmente potrebbe cambiare il mio codice per avere un elenco di dizionari, ma poiché non ho davvero bisogno di un elenco di dizionari, volevo sapere se esiste una soluzione più semplice.




Praticamente uguale alla risposta di Hank Gay;


    sorted([(value,key) for (key,value) in mydict.items()])

O ottimizzato un po 'come suggerito da John Fouhy;


    sorted((value,key) for (key,value) in mydict.items())




Perché non provare questo approccio. Definiamo un dizionario chiamato mydict con i seguenti dati:

mydict = {'carl':40,
          'alan':2,
          'bob':1,
          'danny':3}

Se si volesse ordinare il dizionario per chiavi, si potrebbe fare qualcosa come:

for key in sorted(mydict.iterkeys()):
    print "%s: %s" % (key, mydict[key])

Questo dovrebbe restituire il seguente risultato:

alan: 2
bob: 1
carl: 40
danny: 3

D'altra parte, se si volesse ordinare un dizionario per valore (come viene chiesto nella domanda), si potrebbe fare quanto segue:

for key, value in sorted(mydict.iteritems(), key=lambda (k,v): (v,k)):
    print "%s: %s" % (key, value)

Il risultato di questo comando (ordinando il dizionario per valore) dovrebbe restituire quanto segue:

bob: 1
alan: 2
danny: 3
carl: 40



Se i tuoi valori sono interi e usi Python 2.7 o successivi, puoi usare collections.Counter invece di dict . Il metodo most_common ti fornirà tutti gli elementi, ordinati in base al valore.




Puoi anche usare la funzione personalizzata che può essere passata alla chiave.

def dict_val(x):
    return x[1]
x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
sorted_x = sorted(x.items(), key=dict_val)

Un altro modo per fare è usare la funzione labmda

x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
sorted_x = sorted(x.items(), key=lambda t: t[1])



In Python 2.7, fai semplicemente:

from collections import OrderedDict
# regular unsorted dictionary
d = {'banana': 3, 'apple':4, 'pear': 1, 'orange': 2}

# dictionary sorted by key
OrderedDict(sorted(d.items(), key=lambda t: t[0]))
OrderedDict([('apple', 4), ('banana', 3), ('orange', 2), ('pear', 1)])

# dictionary sorted by value
OrderedDict(sorted(d.items(), key=lambda t: t[1]))
OrderedDict([('pear', 1), ('orange', 2), ('banana', 3), ('apple', 4)])

copia-incolla da: http://docs.python.org/dev/library/collections.html#ordereddict-examples-and-recipes

Godere ;-)




AGGIORNAMENTO: 5 DICEMBRE 2015 utilizzando Python 3.5

Anche se ho trovato la risposta accettata utile, sono stato anche sorpreso dal fatto che non è stato aggiornato per fare riferimento a OrderedDict dal modulo delle collezioni di librerie standard come un'alternativa valida e moderna - progettata per risolvere esattamente questo tipo di problema.

from operator import itemgetter
from collections import OrderedDict

x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
sorted_x = OrderedDict(sorted(x.items(), key=itemgetter(1)))
# OrderedDict([(0, 0), (2, 1), (1, 2), (4, 3), (3, 4)])

La documentazione ufficiale di OrderedDict offre anche un esempio molto simile, ma usando un lambda per la funzione sort:

# regular unsorted dictionary
d = {'banana': 3, 'apple':4, 'pear': 1, 'orange': 2}

# dictionary sorted by value
OrderedDict(sorted(d.items(), key=lambda t: t[1]))
# OrderedDict([('pear', 1), ('orange', 2), ('banana', 3), ('apple', 4)])



Dizionario fornito

e = {1:39, 4:34, 7:110, 2:87}

Ordinamento

sred = sorted(e.items(), key=lambda value: value[1])

Risultato

[(4, 34), (1, 39), (2, 87), (7, 110)]

È possibile utilizzare una funzione lambda per ordinare le voci per valore e memorizzarle elaborate all'interno di una variabile, in questo caso sred con e il dizionario originale.

Spero possa aiutare!




Se i valori sono numerici, puoi utilizzare anche Contatore dalle raccolte

from collections import Counter

x={'hello':1,'python':5, 'world':3}
c=Counter(x)
print c.most_common()


>> [('python', 5), ('world', 3), ('hello', 1)]    



Puoi usare le collections.Counter . Nota, questo funzionerà sia per valori numerici che non numerici.

>>> x = {1: 2, 3: 4, 4:3, 2:1, 0:0}
>>> from collections import Counter
>>> #To sort in reverse order
>>> Counter(x).most_common()
[(3, 4), (4, 3), (1, 2), (2, 1), (0, 0)]
>>> #To sort in ascending order
>>> Counter(x).most_common()[::-1]
[(0, 0), (2, 1), (1, 2), (4, 3), (3, 4)]
>>> #To get a dictionary sorted by values
>>> from collections import OrderedDict
>>> OrderedDict(Counter(x).most_common()[::-1])
OrderedDict([(0, 0), (2, 1), (1, 2), (4, 3), (3, 4)])



Ecco una soluzione che utilizza zip su d.values() e d.keys() . Alcune linee in basso su questo collegamento (su Oggetti vista dizionario) sono:

Ciò consente la creazione di coppie (valore, chiave) usando zip (): pairs = zip (d.values ​​(), d.keys ()).

Quindi possiamo fare quanto segue:

d = {'key1': 874.7, 'key2': 5, 'key3': 8.1}

d_sorted = sorted(zip(d.values(), d.keys()))

print d_sorted 
# prints: [(5, 'key2'), (8.1, 'key3'), (874.7, 'key1')]



Naturalmente, ricorda, devi usare OrderedDict perché i normali dizionari Python non mantengono l'ordine originale.

from collections import OrderedDict
a = OrderedDict(sorted(originalDict.items(), key = lambda x: x[1]))

Se non hai Python 2.7 o versioni successive, il meglio che puoi fare è iterare sui valori in una funzione generatore. (C'è un OrderedDict per 2.4 e 2.6 here , ma

a) I don't know about how well it works 

e

b) You have to download and install it of course. If you do not have administrative access, then I'm afraid the option's out.)
def gen(originalDict):
    for x,y in sorted(zip(originalDict.keys(), originalDict.values()), key = lambda z: z[1]):
        yield (x, y)
    #Yields as a tuple with (key, value). You can iterate with conditional clauses to get what you want. 

for bleh, meh in gen(myDict):
    if bleh == "foo":
        print(myDict[bleh])

Puoi anche stampare ogni valore

for bleh, meh in gen(myDict):
    print(bleh,meh)

Ricordarsi di rimuovere le parentesi dopo la stampa se non si utilizza Python 3.0 o successivo




Sono arrivato con questo,

import operator    
x = {1: 2, 3: 4, 4:3, 2:1, 0:0}
sorted_x = {k[0]:k[1] for k in sorted(x.items(), key=operator.itemgetter(1))}

Per Python 3.x: x.items() sostituisce iteritems() .

>>> sorted_x
{0: 0, 1: 2, 2: 1, 3: 4, 4: 3}

Oppure prova con collections.OrderedDict !

x = {1: 2, 3: 4, 4:3, 2:1, 0:0}
from collections import OrderedDict

od1 = OrderedDict(sorted(x.items(), key=lambda t: t[1]))



Questo restituisce l'elenco delle coppie chiave-valore nel dizionario, ordinate per valore dal più alto al più basso:

sorted(d.items(), key=lambda x: x[1], reverse=True)

Per il dizionario ordinato per chiave, utilizzare quanto segue:

sorted(d.items(), reverse=True)

Il ritorno è una lista di tuple perché i dizionari stessi non possono essere ordinati.

Questo può essere sia stampato che inviato ad ulteriori calcoli.




I dadi non possono essere ordinati, ma è possibile creare un elenco ordinato da loro.

Un elenco ordinato di valori di dict:

sorted(d.values())

Un elenco di coppie (chiave, valore), ordinate per valore:

from operator import itemgetter
sorted(d.items(), key=itemgetter(1))





Related