2015-12-14 3 views
4

Есть ли умный питонический способ проверить, есть ли элемент (ключ, значение) в dict?Как проверить, присутствует ли пара слов-значение в словаре?

a={'a':1,'b':2,'c':3} 
b={'a':1} 
c={'a':2} 

b in a: 
--> True 
c in a: 
--> False 
+2

почему бы не использовать '.get()'? – letsc

+1

@letsc: отправьте его как ответ – GingerPlusPlus

+3

Возможный дубликат [Проверить, существует ли данный ключ в словаре] (http://stackoverflow.com/questions/1602934/check-if-a-given-key-already- Существует-в-словаре) – Aaron

ответ

8

Использовать свойство короткого замыкания and. Таким образом, если левая рука ложна, тогда вы не получите KeyError, проверяя значение.

>>> a={'a':1,'b':2,'c':3} 
>>> key,value = 'c',3    # Key and value present 
>>> key in a and value == a[key] 
True 
>>> key,value = 'b',3    # value absent 
>>> key in a and value == a[key] 
False 
>>> key,value = 'z',3    # Key absent 
>>> key in a and value == a[key] 
False 
+0

Это выполняет два словарных поиска, когда один из них достаточно. – GingerPlusPlus

+0

@GingerPlusPlus Это лучше в худшем случае, если не в лучшем случае. –

+0

Можете ли вы уточнить? Почему это лучше, чем '.get()'? – GingerPlusPlus

1

Вы можете проверить кортеж ключа, значение по отношению к словарю .items().

test = {'a': 1, 'b': 2} 
print(('a', 1) in test.items()) 
>>> True 
+4

Это очень медленно, поскольку он создает список элементов и выполняет линейный поиск через список. – user2357112

+1

@ user2357112 Правда. Если это критически важная часть программы, я бы пошел с ответом Бхаргава Рао, но я бы сказал, что это более читаемо. –

+0

Будет ли 'iteritems()' быстрее? Я имею в виду, все еще линейный поиск, но память мудрая, это генератор. –

6

Вы помечено это 2.7, в отличие от 2.x, так что вы можете проверить, является ли кортеж в ДИКТ-х viewitems:

(key, value) in d.viewitems() 

Под капотом, это в основном делает key in d and d[key] == value.

В Python 3, viewitems всего items, но не используйте items в Python 2! Это построит список и выполнит линейный поиск, используя O (n) время и пространство, чтобы сделать то, что должно быть быстрой проверкой O (1).

+0

Не 'iteritems' в Python2.x считается' items' в Python3? Документы говорят, что 'viewitems' является объектом динамического представления. –

+0

@ cricket_007: Нет, 'iteritems' в Python 2 не имеет эквивалента Python 3. Python 3 'items' - это объект динамического представления, такой как« viewitems »Python 2.7. – user2357112

3
>>> a = {'a': 1, 'b': 2, 'c': 3} 
>>> b = {'a': 1} 
>>> c = {'a': 2} 

Во-первых вот способ, который работает для python2 и Python3

>>> all(k in a and a[k] == b[k] for k in b) 
True 
>>> all(k in a and a[k] == c[k] for k in c) 
False 

В Python3 вы также можете использовать

>>> b.items() <= a.items() 
True 
>>> c.items() <= a.items() 
False 

Для python2, эквивалент является

>>> b.viewitems() <= a.viewitems() 
True 
>>> c.viewitems() <= a.viewitems() 
False 
+0

Проверка 'if k in a' означает, что проверка' all' будет сообщать '{'d': 4}' как подпункт 'a'. – user2357112

+0

@ пользователь2357112, спасибо. починил это –

0

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

# this doesn't work if `None` is a possible value 
# but you can use a different sentinal value in that case 
a.get('a') == 1 

Использование Try/за исключением:

# more verbose than using `get`, but more foolproof also 
a = {'a':1,'b':2,'c':3} 
try: 
    has_item = a['a'] == 1 
except KeyError: 
    has_item = False 

print(has_item) 

Другие ответы, предполагающие items в Python3 и viewitems в Python 2.7 легче читать и более идиоматических, но предложения в этом ответе будет работать в обеих версиях Python без кода совместимости и будет работать в постоянное время. Выбрать свой яд.

0
a.get('a') == 1 
=> True 
    a.get('a') == 2 
=> False 

если None действует пункт:

{'x': None}.get('x', object()) is None 
2

Преобразование мой комментарий в ответ:

Используйте dict.get метод, который уже представлен в качестве встроенного метода (и я полагаю, является наиболее pythonic)

>>> dict = {'Name': 'Anakin', 'Age': 27} 
>>> dict.get('Age') 
27 
>>> dict.get('Gender', 'None') 
'None' 
>>> 

Согласно документам -

get (key, default) - Возвращает значение для ключа, если ключ находится в словаре, иначе по умолчанию. Если значение по умолчанию не задано, по умолчанию оно равно None, так что этот метод никогда не вызывает KeyError.

0

Использование .get, как правило, лучший способ проверить, существует ли пара ключей.

if my_dict.get('some_key'): 
    # Do something 

Существует один нюанс, если ключ существует, но falsy то провалит тест, который не может быть то, что вы хотите. Имейте в виду, что это редко бывает. Теперь обратная проблема является более частым. Это использует in для проверки наличия ключа. Я часто обнаружил эту проблему при чтении файлов csv.

Пример

# csv looks something like this: 
a,b 
1,1 
1, 

# now the code 
import csv 
with open('path/to/file', 'r') as fh: 
    reader = csv.DictReader(fh) # reader is basically a list of dicts 
    for row_d in reader: 
    if 'b' in row_d: 
     # On the second iteration of this loop, b maps to the empty string but 
     # passes this condition statement, most of the time you won't want 
     # this. Using .get would be better for most things here. 
Смежные вопросы