Как проверить, что несколько ключей находятся в dict за один проход?

Я хочу сделать что-то вроде:

foo = {'foo':1,'zip':2,'zam':3,'bar':4}

if ("foo","bar") in foo:
    #do stuff

Как проверить, находятся ли "foo" и "bar" в dict foo?

Ответ 1

Хорошо, вы могли бы сделать это:

>>> if all (k in foo for k in ("foo","bar")):
...     print "They're there!"
...
They're there!

Ответ 2

if set(("foo", "bar")) <= set(myDict): ...

Ответ 3

Простая эталонная установка для 3 альтернатив.

Поместите свои собственные значения для D и Q


>>> from timeit import Timer
>>> setup='''from random import randint as R;d=dict((str(R(0,1000000)),R(0,1000000)) for i in range(D));q=dict((str(R(0,1000000)),R(0,1000000)) for i in range(Q));print("looking for %s items in %s"%(len(q),len(d)))'''

>>> Timer('set(q) <= set(d)','D=1000000;Q=100;'+setup).timeit(1)
looking for 100 items in 632499
0.28672504425048828

#This one only works for Python3
>>> Timer('set(q) <= d.keys()','D=1000000;Q=100;'+setup).timeit(1)
looking for 100 items in 632084
2.5987625122070312e-05

>>> Timer('all(k in d for k in q)','D=1000000;Q=100;'+setup).timeit(1)
looking for 100 items in 632219
1.1920928955078125e-05

Ответ 4

Вам не нужно обертывать левую сторону в наборе. Вы можете просто сделать это:

if {'foo', 'bar'} <= set(some_dict):
    pass

Это также работает лучше, чем решение all(k in d...).

Ответ 5

Использование устанавливает:

if set(("foo", "bar")).issubset(foo):
    #do stuff

В качестве альтернативы:

if set(("foo", "bar")) <= set(foo):
    #do stuff

Ответ 6

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

if all(key in foo for key in ["foo","bar"]):
    # do stuff
    pass

Ответ 7

Хотя мне нравится Алекс Мартелли, мне кажется, что это не Pythonic. То есть, я думал, что важная часть быть Pythonic должна быть легко понятна. С этой целью <= нелегко понять.

В то время как больше символов, использование issubset(), как предлагает ответ Карла Фойгтланда, более понятно. Поскольку этот метод может использовать словарь в качестве аргумента, короткое, понятное решение:

foo = {'foo': 1, 'zip': 2, 'zam': 3, 'bar': 4}

if set(('foo', 'bar')).issubset(foo):
    #do stuff

Я хотел бы использовать {'foo', 'bar'} вместо set(('foo', 'bar')), потому что он короче. Тем не менее, это не так понятно, и я думаю, что скобки слишком легко запутаны как словарь.

Ответ 8

Решение Alex Martelli set(queries) <= set(my_dict) является самым коротким кодом, но может быть не самым быстрым. Предположим, что Q = len (запросы) и D = len (my_dict).

Это делает O (Q) + O (D), чтобы сделать два набора, а затем (надеется!) только O (min (Q, D)) выполнить тест подмножества - считая, конечно, что набор Python look-up - O (1) - это худший случай (когда ответ True).

Решение генератора hughdbrown (et al.) all(k in my_dict for k in queries) является наихудшим случаем O (Q).

Усложняющие факторы:
(1) петли в гаджете на основе набора выполняются со скоростью C, тогда как гаджет-на-основе циклируется по байт-коду.
(2) Абонент гаджета на любой основе может использовать любое знание вероятности неспособности упорядочить элементы запроса соответственно, в то время как гаджет на основе набора не допускает такого контроля.

Как всегда, если скорость важна, бенчмаркинг в рабочих условиях является хорошей идеей.

Ответ 9

Я думаю, что это самое умное и питоническое.

{'key1','key2'} <= my_dict.keys()

Ответ 10

Как насчет использования лямбда?

 if reduce( (lambda x, y: x and foo.has_key(y) ), [ True, "foo", "bar"] ): # do stuff

Ответ 11

Если вы хотите:

  • также получают значения для ключей
  • проверить более одного диктатора

то

from operator import itemgetter
foo = {'foo':1,'zip':2,'zam':3,'bar':4}
keys = ("foo","bar") 
getter = itemgetter(*keys) # returns all values
try:
    values = getter(foo)
except KeyError:
    # not both keys exist
    pass

Ответ 12

Не предполагать, что это не то, о чем вы не думали, но я считаю, что самая простая вещь обычно лучшая:

if ("foo" in foo) and ("bar" in foo):
    # do stuff

Ответ 13

>>> if 'foo' in foo and 'bar' in foo:
...     print 'yes'
... 
yes

Jason,() не нужны в Python.

Ответ 14

Вы также можете использовать .issubset()

>>> {0, 1}.issubset({0, 1, 2})
True
>>> {1}.issubset({0, 1, 2})
True
>>> {1}.issubset({'A', 'B', 'C'})
False
>>> {1}.issubset(())
False

Ответ 15

>>> ok
{'five': '5', 'two': '2', 'one': '1'}

>>> if ('two' and 'one' and 'five') in ok:
...   print "cool"
... 
cool

Это похоже на работу