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

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

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

我的问题:

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

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


当前回答

我是python的新手,但我最终做了类似于@mouad的事情

unmatched_item = set(dict_1.items()) ^ set(dict_2.items())
len(unmatched_item) # should be 0

异或操作符(^)应该删除字典中的所有元素,如果它们在两个字典中都相同。

其他回答

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

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)

希望有帮助!

由于似乎没有人提到deepdiff,为了完整起见,我将在这里添加它。我发现它非常方便获得(嵌套)对象的差异:

安装

pip install deepdiff

示例代码

import deepdiff
import json

dict_1 = {
    "a": 1,
    "nested": {
        "b": 1,
    }
}

dict_2 = {
    "a": 2,
    "nested": {
        "b": 2,
    }
}

diff = deepdiff.DeepDiff(dict_1, dict_2)
print(json.dumps(diff, indent=4))

输出

{
    "values_changed": {
        "root['a']": {
            "new_value": 2,
            "old_value": 1
        },
        "root['nested']['b']": {
            "new_value": 2,
            "old_value": 1
        }
    }
}

注意关于检查结果的漂亮打印:如果两个字典具有相同的属性键(可能与示例中的属性值不同),上面的代码就可以工作。但是,如果存在一个“extra”属性是字典之一,json.dumps()将失败

TypeError: Object of type PrettyOrderedSet is not JSON serializable

解决方案:使用diff.to_json()和json.loads() / json.dumps()来漂亮地打印:

import deepdiff
import json

dict_1 = {
    "a": 1,
    "nested": {
        "b": 1,
    },
    "extra": 3
}

dict_2 = {
    "a": 2,
    "nested": {
        "b": 2,
    }
}

diff = deepdiff.DeepDiff(dict_1, dict_2)
print(json.dumps(json.loads(diff.to_json()), indent=4))  

输出:

{
    "dictionary_item_removed": [
        "root['extra']"
    ],
    "values_changed": {
        "root['a']": {
            "new_value": 2,
            "old_value": 1
        },
        "root['nested']['b']": {
            "new_value": 2,
            "old_value": 1
        }
    }
}

替代方案:使用pprint,结果是不同的格式:

import pprint

# same code as above

pprint.pprint(diff, indent=4)

输出:

{   'dictionary_item_removed': [root['extra']],
    'values_changed': {   "root['a']": {   'new_value': 2,
                                           'old_value': 1},
                          "root['nested']['b']": {   'new_value': 2,
                                                     'old_value': 1}}}

你可以用下面的方法写出你自己的函数。

class Solution:
    def find_if_dict_equal(self,dict1,dict2):
        dict1_keys=list(dict1.keys())
        dict2_keys=list(dict2.keys())
        if len(dict1_keys)!=len(dict2_keys):
            return False
        for i in dict1_keys:
            if i not in dict2 or dict2[i]!=dict1[i]:
                return False
        return True
        
    def findAnagrams(self, s, p):
        if len(s)<len(p):
            return []
        p_dict={}
        for i in p:
            if i not in p_dict:
                p_dict[i]=0
            p_dict[i]+=1
        s_dict={}
        final_list=[]
        for i in s[:len(p)]:
            if i not in s_dict:
                s_dict[i]=0
            s_dict[i]+=1
        if self.find_if_dict_equal(s_dict,p_dict):
            final_list.append(0)
        for i in range(len(p),len(s)):
            element_to_add=s[i]
            element_to_remove=s[i-len(p)]
            if element_to_add not in s_dict:
                s_dict[element_to_add]=0
            s_dict[element_to_add]+=1
            s_dict[element_to_remove]-=1
            if s_dict[element_to_remove]==0:
                del s_dict[element_to_remove]
            if self.find_if_dict_equal(s_dict,p_dict):
                final_list.append(i-len(p)+1)
        return final_list

下面的代码将帮助您比较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

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

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