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