Ответ 1
>>> 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']
Я хотел бы просто обновить этот ответ, чтобы также продемонстрировать решение @glarrain, которое я считаю своим долгом использовать.
[k for k in d if d[k] > 6]
Это полностью перекрестная совместимость и не требует смутного изменения от .iteritems
(.iteritems
позволяет избежать сохранения списка в память на Python 2, который исправлен в Python 3), до .items
.
@Проф. Фалькен упомянул решение этой проблемы
from six import iteritems
который эффективно устраняет проблемы с перекрестной совместимостью BUT требует, чтобы вы загрузили пакет six
Однако я не полностью согласен с @glarrain в том, что это решение более читаемо, это обсуждение и, возможно, только личное предпочтение, хотя Python должен иметь только один способ сделать это. По-моему, это зависит от ситуации (например, у вас может быть длинное имя словаря, которое вы не хотите вводить дважды, или вы хотите, чтобы значения стали более читаемым именем или какой-либо другой причиной).
Некоторые интересные тайминги:
В Python 2 второе решение выполняется быстрее, в Python 3 они почти точно равны по скорости.
$ 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
Однако это только тесты для небольших словарей, в словарных огромных словах я уверен, что без поиска словарного ключа (d[k]
) бы сделать .items
намного быстрее.
И это выглядит так.
$ 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