2009-12-15 6 views
25

В настоящее время я использую следующую функцию для сравнения значений словаря. Есть ли более быстрый или лучший способ сделать это?Есть ли лучший способ сравнить значения словаря

match = True 
for keys in dict1: 
    if dict1[keys] != dict2[keys]: 
     match = False 
     print keys 
     print dict1[keys], 
     print '->' , 
     print dict2[keys] 

Редактировать: Оба ключа содержат одинаковые ключи.

+0

нужно немного разъяснений ... Вы пытаетесь определить, если dict1 и dict2 содержат точно такие же вещи? Или может dict2 содержать другие значения, которые не указаны в dict1? Кроме того, вам нужно отображать все ключи, которые не совпадают? –

+0

Мне нужно показать все значения, которые не совпадают. У Dict2 есть те же ключи, что и dict1 – randomThought

+0

Вот о чем я тогда напишу. Вы можете 'print dict1 [keys]," -> ", dict2 [keys]' в одной строке. –

ответ

30

Если у dicts есть одинаковые наборы ключей, и вам нужны все эти отпечатки для любой разницы в стоимости, вы не можете многое сделать; может быть что-то вроде:

diffkeys = [k for k in dict1 if dict1[k] != dict2[k]] 
for k in diffkeys: 
    print k, ':', dict1[k], '->', dict2[k] 

в значительной степени соответствует тому, что у вас есть, но вы могли бы получить более хорошее представление, например, путем сортировки diffkeys перед вами петли на нем.

1

Если вы просто сравнивая равенства, вы можете просто сделать это:

if not dict1 == dict2: 
    match = False 

В противном случае, единственная крупная проблема, которую я вижу, что вы собираетесь получить исключение KeyError, если есть ключ в dict1, что не в dict2, так что вы можете сделать что-то вроде этого:

for key in dict1: 
    if not key in dict2 or dict1[key] != dict2[key]: 
     match = False 

вы можете сжать это в понимании, чтобы просто получить список ключей, которые не соответствуют также:

mismatch_keys = [key for key in x if not key in y or x[key] != y[key]] 
match = not bool(mismatch_keys) #If the list is not empty, they don't match 
for key in mismatch_keys: 
    print key 
    print '%s -> %s' % (dict1[key],dict2[key]) 

Единственная другая оптимизация, о которой я могу думать, может состоять в том, чтобы использовать «len (dict)», чтобы выяснить, какой dict имеет меньше записей и прокручивает этот первый, чтобы иметь самый короткий цикл.

+0

'match = not (dict1 == dict2)'? – vinntec

+0

@vinntec Разве это не просто 'dict1! = Dict2'? –

+0

Я предлагал больше, чтобы избежать patter 'if condition then True else False'. Кроме того, в зависимости от языка и вовлеченных типов иногда 'not (==)' не совпадает с '! =', Поэтому я просто осторожен. – vinntec

1
>>> a = {'x': 1, 'y': 2} 
>>> b = {'y': 2, 'x': 1} 
>>> print a == b 
True 
>>> c = {'z': 1} 
>>> print a == c 
False 
>>> 
5

Эмм, вы описываете dict1 == dict2 (проверьте, если Boths dicts равны)

Но что ваш код делает all(dict1[k]==dict2[k] for k in dict1) (проверьте, если все записи в dict1 равны таковым в dict2)

+2

Который пропускает случай, когда dict2 имеет * дополнительные * ключи над dict1, поэтому они фактически не ведут себя одинаково. – ThomasH

9

Вы можете использовать наборы для этого тоже

>>> a = {'x': 1, 'y': 2} 
>>> b = {'y': 2, 'x': 1} 
>>> set(a.iteritems())-set(b.iteritems()) 
set([]) 
>>> a['y']=3 
>>> set(a.iteritems())-set(b.iteritems()) 
set([('y', 3)]) 
>>> set(b.iteritems())-set(a.iteritems()) 
set([('y', 2)]) 
>>> set(b.iteritems())^set(a.iteritems()) 
set([('y', 3), ('y', 2)]) 
+3

Это работает очень хорошо, если одно из значений не сотрясается (например, «список»). 'set ({'x': []}. iteritems())' поднимет 'TypeError'. – 2013-08-24 21:17:39

+0

@ user212218 - Для статей словаря с неотображаемыми объектами см. Здесь: http://stackoverflow.com/questions/43504568/compare-dictionaries-with-unhashable-or-uncomparable-values-eg-lists-or-data – Afflatus

92

Если истинная цель этого вопроса является сравнение между dicts (а не печать различий), то ответ

dict1 == dict2 

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

  • количество ключей (если они не совпадают, то dicts не равен)
  • имен ключей (если они не совпадают, то они не равны)
  • значения каждый ключ (они должны быть «==», тоже)

последним пункт появляется снова тривиален, но acutally интересно, как это означает, что все это применяется рекурсивно к вложенной dicts, а также. Например.

m1 = {'f':True} 
m2 = {'f':True} 
m3 = {'a':1, 2:2, 3:m1} 
m4 = {'a':1, 2:2, 3:m2} 
m3 == m4 # True 

Подобная семантика существует для сравнения списков.Все это делает его неинтересным, например, сравните глубокие структуры Json, только с простым «==».

+4

'все это также рекурсивно относится к вложенным диктофонам ». Является ли это явно документированным, а также любые ограничения для сложной вложенной структуры, например dict списка dict и т. д.? – Medorator

+1

Я не могу придумать ни одной части документации, в которой говорится об этом. Мой ответ - опыт и эксперименты. Я рекомендую вам то же самое, например. проверьте сравнение некоторых интересующих вас структур данных. – ThomasH

+2

Вау, это правда - '==' делает глубокое сравнение, по крайней мере для базовых типов! Попробуйте в REPL: 'a = {" a ": False, 'b': [1,2, {'foo': 'bar', 'zamboni': True, 'cheese': [False, []]}, 3], 'с': Нет}; b = {'c': None, 'a': False, 'b': [1,2, {'cheese': [False, []], 'foo': 'bar', 'zamboni': True} , 3]}; a == b'. Круто! –

-1

Если ваши словари глубоко вложены, и если они содержат различные типы коллекций, вы можете преобразовать их в строку json и сравнить.

import json 
match = (json.dumps(dict1) == json.dumps(dict2)) 

caveat- это решение не может работать, если ваши словари имеют двоичные строки в значении, так как это не JSon сериализуемый

+3

Примечание. По крайней мере, в Python 2.6 порядок не гарантированно согласован, поэтому можно использовать один и тот же ключ: значения в обоих dicts генерируют разные json.dumps(), если ключи находятся в другом порядке и состоят из некоторые строки. (Честно говоря, я не мог судить о точных правилах, но в моих двух диктофонах смена ведущего «b» на «v» в том же ключе с обеих сторон сравнения приводит к тому, что результирующие строки будут отличаться, повторяемо.) – DreadPirateShawn

+0

Было бы лучше использовать функцию глубокого равенства. Это было бы дешевле и действительно работало бы должным образом. –

1

Не уверен, если это поможет, но в моем приложении, я должен был проверить, если словарь имеет изменилось.

Делать это не будет работать, так как в основном это все тот же объект:

val={'A':1,'B':2} 
old_val=val 

val['A']=10 
if old_val != val: 
    print('changed') 

Использование копирования/DeepCopy работы:

import copy 
val={'A':1,'B':2} 
old_val=copy.deepcopy(val) 

val['A']=10 
if old_val != val: 
    print('changed')