Есть ли лучший способ сравнить значения словаря - PullRequest
40 голосов
/ 16 декабря 2009

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

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

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

Ответы [ 8 ]

143 голосов
/ 12 апреля 2011

Если истинным намерением вопроса является сравнение различий (а не печатных различий), ответ будет

dict1 == dict2

Это было упомянуто ранее, но я чувствовал, что это слегка тонет в других битах информации. Это может показаться поверхностным, но сравнение значений у 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, наедине с простым "==".

36 голосов
/ 16 декабря 2009

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

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

в значительной степени эквивалентно тому, что у вас есть, но вы можете получить более приятное представление, например, отсортировав diffkeys перед тем, как зацикливаться на нем.

9 голосов
/ 16 декабря 2009

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

>>> 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)])
7 голосов
/ 16 декабря 2009

Хм, вы описываете dict1 == dict2 (проверьте, равны ли оба значения)

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

2 голосов
/ 28 апреля 2016

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

Выполнение этого не будет работать, поскольку в основном это все тот же объект:

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

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

Использование копий / копий:

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

val['A']=10
if old_val != val:
  print('changed')
1 голос
/ 16 декабря 2009
>>> a = {'x': 1, 'y': 2}
>>> b = {'y': 2, 'x': 1}
>>> print a == b
True
>>> c = {'z': 1}
>>> print a == c
False
>>> 
1 голос
/ 16 декабря 2009

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

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 голосов
/ 13 августа 2015

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...