Подтвердить что ты не робот

Как фильтровать словарные ключи на основе его соответствующих значений

У меня есть:

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

Я хочу перебрать этот словарь, но над значениями вместо ключей, поэтому я могу использовать значения в другой функции.

Например, я хочу проверить, какие словарные значения больше, чем 6, а затем сохранить их ключи в списке. Мой код выглядит следующим образом:

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

а затем в идеальном мире list будет отображаться все ключи, значение которых больше, чем 6. Однако мой цикл for выполняет только итерацию по клавишам; Я хотел бы изменить это на значения!

Любая помощь приветствуется. спасибо

4b9b3361

Ответ 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

Ответ 2

Чтобы просто получить значения, используйте dictionary.values()

Чтобы получить пары ключевых значений, используйте dictionary.items()

Ответ 3

Используйте словарь items или iteritems в словаре. Что-то вроде:

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

Ответ 4

Как насчет этого:

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

Ответ 5

Это зависит от того, хотите ли вы изменить словарь (добавить или удалить элементы) или нет. Если нет, вы можете попробовать:

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

Альтернативно, если вы изменяете словарь, вы должны перебирать копию значений:

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

Если вам нужны оба ключа и значения, вы можете перебирать пары с помощью dictionary.iteritems() или dictionary.items()

Ответ 6

Я думаю, что лучший способ сделать это (учитывая переход на Python 3) -

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

Критерии "наилучшего" являются читабельностью.

(Отказ от ответственности: мой ответ основан на Alex Martelli, отвечая на другой вопрос fooobar.com/info/44262/... и @jamylak на этот вопрос)