我有两本字典,但为了简化起见,我就选这两本:

>>> x = dict(a=1, b=2)
>>> y = dict(a=2, b=2)

现在,我想比较x中的每个键值对在y中是否有相同的对应值,所以我这样写:

>>> for x_values, y_values in zip(x.iteritems(), y.iteritems()):
        if x_values == y_values:
            print 'Ok', x_values, y_values
        else:
            print 'Not', x_values, y_values

它的工作原理是返回一个元组,然后比较是否相等。

我的问题:

这对吗?还有更好的办法吗?最好不是在速度上,我说的是代码优雅。

更新:我忘了提到,我必须检查有多少键,值对是相等的。


当前回答

还有一种可能,直到OP的最后一个音符,是比较转储为JSON的字典的哈希值(SHA或MD)。构造哈希的方式保证如果它们相等,源字符串也相等。这是非常快速和数学上合理的。

import json
import hashlib

def hash_dict(d):
    return hashlib.sha1(json.dumps(d, sort_keys=True)).hexdigest()

x = dict(a=1, b=2)
y = dict(a=2, b=2)
z = dict(a=1, b=2)

print(hash_dict(x) == hash_dict(y))
print(hash_dict(x) == hash_dict(z))

其他回答

我正在使用这个解决方案,在Python 3中完美地为我工作


import logging
log = logging.getLogger(__name__)

...

    def deep_compare(self,left, right, level=0):
        if type(left) != type(right):
            log.info("Exit 1 - Different types")
            return False

        elif type(left) is dict:
            # Dict comparison
            for key in left:
                if key not in right:
                    log.info("Exit 2 - missing {} in right".format(key))
                    return False
                else:
                    if not deep_compare(left[str(key)], right[str(key)], level +1 ):
                        log.info("Exit 3 - different children")
                        return False
            return True
        elif type(left) is list:
            # List comparison
            for key in left:
                if key not in right:
                    log.info("Exit 4 - missing {} in right".format(key))
                    return False
                else:
                    if not deep_compare(left[left.index(key)], right[right.index(key)], level +1 ):
                        log.info("Exit 5 - different children")
                        return False
            return True
        else:
            # Other comparison
            return left == right

        return False

它比较dict、list和其他单独实现“==”操作符的类型。 如果你需要比较其他不同的东西,你需要在“If树”中添加一个新的分支。

希望这能有所帮助。

在PyUnit中有一个比较字典的方法。我使用以下两个字典对它进行了测试,它完全符合您的要求。

d1 = {1: "value1",
      2: [{"subKey1":"subValue1",
           "subKey2":"subValue2"}]}
d2 = {1: "value1",
      2: [{"subKey2":"subValue2",
           "subKey1": "subValue1"}]
      }


def assertDictEqual(self, d1, d2, msg=None):
        self.assertIsInstance(d1, dict, 'First argument is not a dictionary')
        self.assertIsInstance(d2, dict, 'Second argument is not a dictionary')

        if d1 != d2:
            standardMsg = '%s != %s' % (safe_repr(d1, True), safe_repr(d2, True))
            diff = ('\n' + '\n'.join(difflib.ndiff(
                           pprint.pformat(d1).splitlines(),
                           pprint.pformat(d2).splitlines())))
            standardMsg = self._truncateMessage(standardMsg, diff)
            self.fail(self._formatMessage(msg, standardMsg))

我不建议在生产代码中导入unittest。我的想法是,PyUnit中的源代码可以重新配置,以在生产环境中运行。它使用pprint来“漂亮地打印”字典。调整这段代码以使其“适合生产”似乎很容易。

还有一种可能,直到OP的最后一个音符,是比较转储为JSON的字典的哈希值(SHA或MD)。构造哈希的方式保证如果它们相等,源字符串也相等。这是非常快速和数学上合理的。

import json
import hashlib

def hash_dict(d):
    return hashlib.sha1(json.dumps(d, sort_keys=True)).hexdigest()

x = dict(a=1, b=2)
y = dict(a=2, b=2)
z = dict(a=1, b=2)

print(hash_dict(x) == hash_dict(y))
print(hash_dict(x) == hash_dict(z))

为什么不只是遍历一个字典,并在过程中检查另一个字典(假设两个字典都有相同的键)?

x = dict(a=1, b=2)
y = dict(a=2, b=2)

for key, val in x.items():
    if val == y[key]:
        print ('Ok', val, y[key])
    else:
        print ('Not', val, y[key])

输出:

Not 1 2
Ok 2 2

对两个字典进行深度比较的最简单的方法(也是最健壮的方法之一)是将它们序列化为JSON格式,对键进行排序,并比较字符串结果:

import json
if json.dumps(x, sort_keys=True) == json.dumps(y, sort_keys=True):
   ... Do something ...