比较Python词典和嵌套词典

rka*_*kam 13 python comparison dictionary

我知道有几个类似的问题,但我的问题对我来说是完全不同的.我有两个词典:

d1 = {'a': {'b': {'cs': 10}, 'd': {'cs': 20}}}
d2 = {'a': {'b': {'cs': 30}, 'd': {'cs': 20}}, 'newa': {'q': {'cs': 50}}}
Run Code Online (Sandbox Code Playgroud)

d1有钥匙'a',并d2有钥匙'a''newa'(换句话说d1是我的旧词典,d2是我的新词典).

我想迭代这些字典,这样,如果键是相同的,检查它的值(嵌套字典),例如当我找到键'a'd2,我将检查是否存在'b',如果是,则检查值'cs'(从更改1030),如果这个值改变了我想要打印它.

另一种情况是,我想重点'newa'd2为新添加的关键.

因此,在迭代这两个dicts后,这是预期的输出:

"d2" has new key "newa"
Value of "cs" is changed from 10 to 30 of key "b" which is of key "a"
Run Code Online (Sandbox Code Playgroud)

我有以下代码与我,我正在尝试许多循环,虽然不起作用,但也不是一个好的选项,因此我想找到是否可以用递归代码得到预期的输出.

for k, v in d1.iteritems():
    for k1, v1 in d2.iteritems():
        if k is k1:
            print k
            for k2 in v:
                for k3 in v1:
                    if k2 is k3:
                        print k2, "sub key matched"

        else:
            print "sorry no match found"
Run Code Online (Sandbox Code Playgroud)

ven*_*npa 20

使用递归比较2个词典:

d1= {'a':{'b':{'cs':10},'d':{'cs':20}}}
d2= {'a':{'b':{'cs':30} ,'d':{'cs':20}},'newa':{'q':{'cs':50}}}

def findDiff(d1, d2, path=""):
    for k in d1:
        if (k not in d2):
            print (path, ":")
            print (k + " as key not in d2", "\n")
        else:
            if type(d1[k]) is dict:
                if path == "":
                    path = k
                else:
                    path = path + "->" + k
                findDiff(d1[k],d2[k], path)
            else:
                if d1[k] != d2[k]:
                    print (path, ":")
                    print (" - ", k," : ", d1[k])
                    print (" + ", k," : ", d2[k])

print ("comparing d1 to d2:")
print (findDiff(d1,d2))
print ("comparing d2 to d1:")
print (findDiff(d2,d1))
Run Code Online (Sandbox Code Playgroud)

输出:

d1= {'a':{'b':{'cs':10},'d':{'cs':20}}}
d2= {'a':{'b':{'cs':30} ,'d':{'cs':20}},'newa':{'q':{'cs':50}}}

def findDiff(d1, d2, path=""):
    for k in d1.keys():
        if not d2.has_key(k):
            print path, ":"
            print k + " as key not in d2", "\n"
        else:
            if type(d1[k]) is dict:
                if path == "":
                    path = k
                else:
                    path = path + "->" + k
                findDiff(d1[k],d2[k], path)
            else:
                if d1[k] != d2[k]:
                    print path, ":"
                    print " - ", k," : ", d1[k]
                    print " + ", k," : ", d2[k] 

print "comparing d1 to d2:"
print findDiff(d1,d2)
print "comparing d2 to d1:"
print findDiff(d2,d1)
Run Code Online (Sandbox Code Playgroud)

  • 由于`path`在for循环中被重用,存在一个错误。如果您重命名,以便`if path ==“”:nested_pa​​th = k`,(在else和findDiff中),则不会修改path。 (3认同)

Moh*_*itC 14

修改了user3的代码,使其更好

d1= {'as': 1, 'a':
        {'b':
            {'cs':10,
             'qqq': {'qwe':1}
            },
            'd': {'csd':30}
        }
    }
d2= {'as': 3, 'a':
        {'b':
            {'cs':30,
             'qqq': 123
            },
            'd':{'csd':20}
        },
        'newa':
        {'q':
            {'cs':50}
        }
    }

def compare_dictionaries(dict_1, dict_2, dict_1_name, dict_2_name, path=""):
    """Compare two dictionaries recursively to find non mathcing elements

    Args:
        dict_1: dictionary 1
        dict_2: dictionary 2

    Returns:

    """
    err = ''
    key_err = ''
    value_err = ''
    old_path = path
    for k in dict_1.keys():
        path = old_path + "[%s]" % k
        if not dict_2.has_key(k):
            key_err += "Key %s%s not in %s\n" % (dict_2_name, path, dict_2_name)
        else:
            if isinstance(dict_1[k], dict) and isinstance(dict_2[k], dict):
                err += compare_dictionaries(dict_1[k],dict_2[k],'d1','d2', path)
            else:
                if dict_1[k] != dict_2[k]:
                    value_err += "Value of %s%s (%s) not same as %s%s (%s)\n"\
                        % (dict_1_name, path, dict_1[k], dict_2_name, path, dict_2[k])

    for k in dict_2.keys():
        path = old_path + "[%s]" % k
        if not dict_1.has_key(k):
            key_err += "Key %s%s not in %s\n" % (dict_2_name, path, dict_1_name)

    return key_err + value_err + err


a = compare_dictionaries(d1,d2,'d1','d2')
print a
Run Code Online (Sandbox Code Playgroud)

输出:

Key d2[newa] not in d1
Value of d1[as] (1) not same as d2[as] (3)
Value of d1[a][b][cs] (10) not same as d2[a][b][cs] (30)
Value of d1[a][b][qqq] ({'qwe': 1}) not same as d2[a][b][qqq] (123)
Value of d1[a][d][csd] (30) not same as d2[a][d][csd] (20)
Run Code Online (Sandbox Code Playgroud)

  • 对于Python3版本,分别用“k in dict_2”和“k in dict_1”替换“dict_2.has_key(k)”和“dict_1.has_key(k)” (3认同)

amd*_*dan 12

为什么不使用 deepdiff 库。

请参阅: https: //github.com/seperman/deepdiff

>>> from deepdiff import DeepDiff
>>> t1 = {1:1, 3:3, 4:4}
>>> t2 = {1:1, 3:3, 5:5, 6:6}
>>> ddiff = DeepDiff(t1, t2)
>>> print(ddiff)
{'dictionary_item_added': {'root[5]', 'root[6]'}, 'dictionary_item_removed': {'root[4]'}}
Run Code Online (Sandbox Code Playgroud)

当然它更强大,查看文档了解更多。