2012-05-08 16 views
57

ho:Come filtrare le chiavi del dizionario in base ai suoi valori corrispondenti

dictionary = {"foo":12, "bar":2, "jim":4, "bob": 17} 

voglio iterare questo dizionario, ma nel corso dei valori al posto delle chiavi, così posso utilizzare i valori in un'altra funzione.

Ad esempio, voglio verificare quali valori del dizionario sono maggiori di 6 e quindi memorizzarne le chiavi in ​​un elenco. Il mio codice è simile al seguente:

list = [] 
for c in dictionary: 
    if c > 6: 
     list.append(dictionary[c]) 
print list 

e poi, in un mondo perfetto, list sarebbe caratterizzato da tutte le chiavi il cui valore è maggiore di 6. Tuttavia, il mio ciclo for sta solo iterando sui tasti; Mi piacerebbe cambiarlo con i valori!

Qualsiasi aiuto è molto apprezzato. ringraziamento

+1

Il titolo di questa interrogazione deve essere modificato in quanto ciò che in realtà vuole raggiungere (e le risposte riflettono questo) ottiene le chiavi dei valori corrispondenti in un dizionario per il quale una determinata clausola è vera. Qualcosa come "Come filtrare le chiavi del dizionario in base ai valori corrispondenti" potrebbe essere un'alternativa migliore. – glarrain

risposta

81
>>> d = {"foo": 12, "bar": 2, "jim": 4, "bob": 17} 
>>> [k for k, v in d.items() if v > 6] # Use d.iteritems() on python 2.x 
['bob', 'foo'] 

vorrei aggiornare solo questa risposta per mostrare anche la soluzione da @glarrain cui mi trovo tendente ad utilizzare al giorno d'oggi.

[k for k in d if d[k] > 6] 

Questo è completamente compatibile croce e non richiede un cambiamento di confusione da .iteritems (.iteritems evita salvataggio di un elenco di memoria su Python 2 che è fissato in Python 3) .items.

@ Prof.Falken menzionato una soluzione a questo problema

from six import iteritems 

che fissa in modo efficace i problemi di compatibilità croce, ma richiede di scaricare il pacchetto six

Tuttavia non sarebbe pienamente d'accordo con @glarrain che questa soluzione è più leggibile, è in discussione e forse solo una preferenza personale, anche se si suppone che Python abbia solo un modo per farlo. Secondo me dipende dalla situazione (ad esempio potresti avere un nome di dizionario lungo che non vuoi digitare due volte o vuoi dare un nome più leggibile o altro)

Alcuni tempi interessanti :

In Python 2, la seconda soluzione è più veloce, in Python 3 sono quasi esattamente uguali in velocità raw.


$ python -m timeit -s 'd = {"foo": 12, "bar": 2, "jim": 4, "bob": 17};' '[k for k, v in d.items() if v > 6]' 
1000000 loops, best of 3: 0.772 usec per loop 
$ python -m timeit -s 'd = {"foo": 12, "bar": 2, "jim": 4, "bob": 17};' '[k for k, v in d.iteritems() if v > 6]' 
1000000 loops, best of 3: 0.508 usec per loop 
$ python -m timeit -s 'd = {"foo": 12, "bar": 2, "jim": 4, "bob": 17};' '[k for k in d if d[k] > 6]' 
1000000 loops, best of 3: 0.45 usec per loop 

$ python3 -m timeit -s 'd = {"foo": 12, "bar": 2, "jim": 4, "bob": 17};' '[k for k, v in d.items() if v > 6]' 
1000000 loops, best of 3: 1.02 usec per loop 
$ python3 -m timeit -s 'd = {"foo": 12, "bar": 2, "jim": 4, "bob": 17};' '[k for k in d if d[k] > 6]' 
1000000 loops, best of 3: 1.02 usec per loop 

Tuttavia queste sono solo le prove per i piccoli dizionari, in enormi dizionari Sono abbastanza sicuro che non avendo una ricerca chiave dizionario (d[k]) renderebbe .items molto più veloce. e questo sembra essere il caso

$ python -m timeit -s 'd = {i: i for i in range(-10000000, 10000000)};' -n 1 '[k for k in d if d[k] > 6]' 
1 loops, best of 3: 1.75 sec per loop 
$ python -m timeit -s 'd = {i: i for i in range(-10000000, 10000000)};' -n 1 '[k for k, v in d.iteritems() if v > 6]' 
1 loops, best of 3: 1.71 sec per loop 
$ python3 -m timeit -s 'd = {i: i for i in range(-10000000, 10000000)};' -n 1 '[k for k in d if d[k] > 6]' 
1 loops, best of 3: 3.08 sec per loop 
$ python3 -m timeit -s 'd = {i: i for i in range(-10000000, 10000000)};' -n 1 '[k for k, v in d.items() if v > 6]' 
1 loops, best of 3: 2.47 sec per loop 
+0

+1. Sicuramente la migliore risposta IMHO. –

+5

Per python 2.x, 'd.iteritems()' sarebbe meglio AFAIK. – hochl

+0

Brillante, grazie! – Hoops

4

ne dite di questo:

dictionary = {"foo":12, "bar":2, "jim":4, "bob": 17} 
for val in dictionary.values(): 
    # do something 
+0

Se OP non dispiace, vorrei eliminare la mia risposta. @ Jamylak è decisamente la strada da percorrere. –

36

Per ottenere solo i valori, utilizzare dictionary.values()

Per ottenere coppie di valori chiave, utilizzare dictionary.items()

10

Utilizzare items o iteritems sul dizionario. Qualcosa di simile:

list = [] 
for k, v in dictionary.iteritems(): 
    if v > 6: 
    list.append(k) 
print list 
2

Dipende se si desidera modificare il dizionario (aggiungere o rimuovere elementi) o meno. Se poi non si potrebbe provare:

for value in dictionary.itervalues(): #this returns a generator 
    print "do something with the value" 

In alternativa, se si modifica il dizionario si dovrebbe iterare su una copia di valori:

for value in dictionary.values(): #this returns a list of values 
    print "do something with the value" 

Se volete entrambi i tasti e valori è possibile iterare coppie usando dictionary.iteritems() o dictionary.items()

2

Penso che il modo migliore per farlo (migrazione considerando a Python 3) è

>>> mydict = {'foo': 12, 'bar': 2, 'jim': 4, 'bob': 17} 
>>> [k for k in mydict if mydict[k] > 6] 
['bob', 'foo'] 

I criteri per "il migliore" sono la leggibilità.

(Disclaimer: la mia risposta si basa in risposta di Alex Martelli per altra domanda https://stackoverflow.com/a/3744713/556413 e @ jamylak di a questa domanda)

Problemi correlati