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

>>> 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

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

我的问题:

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

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


当前回答

这是我的答案,使用递归的方式:

def dict_equals(da, db):
    if not isinstance(da, dict) or not isinstance(db, dict):
        return False
    if len(da) != len(db):
        return False
    for da_key in da:
        if da_key not in db:
            return False
        if not isinstance(db[da_key], type(da[da_key])):
            return False
        if isinstance(da[da_key], dict):
            res = dict_equals(da[da_key], db[da_key])
            if res is False:
                return False
        elif da[da_key] != db[da_key]:
            return False
    return True

a = {1:{2:3, 'name': 'cc', "dd": {3:4, 21:"nm"}}}
b = {1:{2:3, 'name': 'cc', "dd": {3:4, 21:"nm"}}}
print dict_equals(a, b)

希望有帮助!

其他回答

只使用:

assert cmp(dict1, dict2) == 0
import json

if json.dumps(dict1) == json.dumps(dict2):
    print("Equal")

在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来“漂亮地打印”字典。调整这段代码以使其“适合生产”似乎很容易。

def dict_compare(d1, d2):
    d1_keys = set(d1.keys())
    d2_keys = set(d2.keys())
    shared_keys = d1_keys.intersection(d2_keys)
    added = d1_keys - d2_keys
    removed = d2_keys - d1_keys
    modified = {o : (d1[o], d2[o]) for o in shared_keys if d1[o] != d2[o]}
    same = set(o for o in shared_keys if d1[o] == d2[o])
    return added, removed, modified, same

x = dict(a=1, b=2)
y = dict(a=2, b=2)
added, removed, modified, same = dict_compare(x, y)

下面的代码将帮助您比较python中的dict列表

def compate_generic_types(object1, object2):
    if isinstance(object1, str) and isinstance(object2, str):
        return object1 == object2
    elif isinstance(object1, unicode) and isinstance(object2, unicode):
        return object1 == object2
    elif isinstance(object1, bool) and isinstance(object2, bool):
        return object1 == object2
    elif isinstance(object1, int) and isinstance(object2, int):
        return object1 == object2
    elif isinstance(object1, float) and isinstance(object2, float):
        return object1 == object2
    elif isinstance(object1, float) and isinstance(object2, int):
        return object1 == float(object2)
    elif isinstance(object1, int) and isinstance(object2, float):
        return float(object1) == object2

    return True

def deep_list_compare(object1, object2):
    retval = True
    count = len(object1)
    object1 = sorted(object1)
    object2 = sorted(object2)
    for x in range(count):
        if isinstance(object1[x], dict) and isinstance(object2[x], dict):
            retval = deep_dict_compare(object1[x], object2[x])
            if retval is False:
                print "Unable to match [{0}] element in list".format(x)
                return False
        elif isinstance(object1[x], list) and isinstance(object2[x], list):
            retval = deep_list_compare(object1[x], object2[x])
            if retval is False:
                print "Unable to match [{0}] element in list".format(x)
                return False
        else:
            retval = compate_generic_types(object1[x], object2[x])
            if retval is False:
                print "Unable to match [{0}] element in list".format(x)
                return False

    return retval

def deep_dict_compare(object1, object2):
    retval = True

    if len(object1) != len(object2):
        return False

    for k in object1.iterkeys():
        obj1 = object1[k]
        obj2 = object2[k]
        if isinstance(obj1, list) and isinstance(obj2, list):
            retval = deep_list_compare(obj1, obj2)
            if retval is False:
                print "Unable to match [{0}]".format(k)
                return False

        elif isinstance(obj1, dict) and isinstance(obj2, dict):
            retval = deep_dict_compare(obj1, obj2)
            if retval is False:
                print "Unable to match [{0}]".format(k)
                return False
        else:
            retval = compate_generic_types(obj1, obj2)
            if retval is False:
                print "Unable to match [{0}]".format(k)
                return False

    return retval