2013-06-01 5 views
1

У меня есть список подстановок полей:Равенство словарей

>>> l = ['A', 'C', 'Z', 'M'] 

я должен был бы проверить равенство 2 словарей в этом списке поиска:

>>> d1 = {'A': 3,'F': 4,'Z': 1} 
>>> d2 = {'B': 0,'A': 3,'C': 7} 

Испытание равенство для любого поля ' x 'в списке выполняется, если выполнено одно из следующих условий:
1.if' x 'отсутствует ни в одном из дефотов
2.if' x 'присутствует, а d1 [x] == d2 [ x]

Функция равенства вернет соответствие ТОЛЬКО ЕСЛИ все поля в списке будут выполнены в соответствии с приведенными выше условиями.

Итак, для вышеуказанных dicts - Z не удался, C не удался, A преуспел, M преуспел.
Однако тест равенства для диктонов должен сообщать об ошибке.

Какой был бы самый короткий способ достичь этого?

+0

Я отредактировал мой ответ, см если то, что вы ищете – AliBZ

+0

я искал короткое замыкание на первую неудачу с чем-то, как и любыми и понимание – IUnknown

+0

@AliBZ: Нет, ответ Ури - это тот ответ, который он ищет. Ответ Ашвина плох, потому что он выполняет линейный поиск для поиска наличия ключа. –

ответ

4

Это, вероятно, самый короткий и элегантна:

all(d1.get(x) == d2.get(x) for x in l) 

Заметим, что если х не в обоих словаре, мы не сравниваете с None None.

EDIT:
- Следующие комментарии, используя генератор (не понимание списка).
- Правильный комментарий Ashwini. Не будет работать, если один из словарей имеет значение «Нет» в качестве значения

EDIT2 (следующий комментарий):
В None не может появиться в словаре, вам нужно иметь другое значение «Нет значения». Если -9999 не будет работать, то просто сгенерировать:

sentinel = object()  #a new object, guaranteed not in dictionary 
all(d1.get(x, sentinel) == d2.get(x, sentinel) for x in l) 
+2

Работает нормально, но может выйти из строя, если '' Z '= None' в 'd1'. –

+1

Хороший ответ, но нет необходимости в квадратных скобках: вы можете передать выражение генератора 'd1.get (x) == d2.get (x) для x в строке' '' '' 'вместо использования понимания списка. –

+2

Удалите скобки и превратите понимание списка в выражение генератора, чтобы сделать его идеальным: 'all (d1.get (x) == d2.get (x) для x в l)'. –

2

Попробуйте это:

success = True 
for x in l: 
    if not (((x not in d1) and (x not in d2)) or (d1.get(x) == d2.get(x))): 
    success = False 
+0

Отступы в Python. –

+0

Я знаю, но я не знаю, как отступать в редакторе – AliBZ

+0

@AliBZ К сожалению, вы не можете нажать вкладку. Вы должны использовать пробелы. Я добавил два пробела в пространстве. – squiguy

2

Вы можете использовать all:

>>> from itertools import chain 
>>> l = ['A', 'C', 'Z', 'M'] 
>>> d1 = {'A': 3,'F': 4,'Z': 1} 
>>> d2 = {'B': 0,'A': 3,'C': 7} 

>>> all(x not in chain(d1,d2) or ((x in d1 and x in d2) and \ 
              d1.get(x) == d2.get(x)) for x in l) 
False 
>>> l = ['Z'] 
>>> d1 = {'A': 3,'F': 4,'Z': None} 

>>> all(x not in chain(d1,d2) or ((x in d1 and x in d2) and \ 
              d1.get(x) == d2.get(x)) for x in l) 
False 

all возвратит True только если все значения Iterable являются True othwerwise он будет возвращать значение False.

+0

@AliBZ о! да, исправил. –

+0

Не вижу необходимости в downvote. Укажите проблему и дайте ему исправить ее. – iruvar

+0

: D ваш ответ намного короче, чем у меня. – AliBZ

Смежные вопросы