一尘不染

两个python字典(键和值)的递归差异

python

因此,我有一个python字典,将其称为d1,然后在稍后的某个时间将该字典的版本称为d2。我想找到d1和之间的所有更改d2。换句话说,添加,删除或更改的所有内容。棘手的是,值可以是整数,字符串,列表或字典,因此需要递归。这是我到目前为止所拥有的:

def dd(d1, d2, ctx=""):
    print "Changes in " + ctx
    for k in d1:
        if k not in d2:
            print k + " removed from d2"
    for k in d2:
        if k not in d1:
            print k + " added in d2"
            continue
        if d2[k] != d1[k]:
            if type(d2[k]) not in (dict, list):
                print k + " changed in d2 to " + str(d2[k])
            else:
                if type(d1[k]) != type(d2[k]):
                    print k + " changed to " + str(d2[k])
                    continue
                else:
                    if type(d2[k]) == dict:
                        dd(d1[k], d2[k], k)
                        continue
    print "Done with changes in " + ctx
    return

除非该值是一个列表,否则它将正常工作。我无法提出一种优雅的方式来处理列表,而又没有在此函数之后重复重复使用该函数的巨大变化if(type(d2) ==list)

有什么想法吗?

编辑:这与这篇文章不同,因为密钥可以更改


阅读 233

收藏
2020-12-20

共1个答案

一尘不染

一种选择是将您遇到的所有列表转换成字典,并将索引作为键。例如:

# add this function to the same module
def list_to_dict(l):
    return dict(zip(map(str, range(len(l))), l))



# add this code under the 'if type(d2[k]) == dict' block
                    elif type(d2[k]) == list:
                        dd(list_to_dict(d1[k]), list_to_dict(d2[k]), k)

这是带有注释的示例词典的输出:

>>> d1 = {"name":"Joe", "Pets":[{"name":"spot", "species":"dog"}]}
>>> d2 = {"name":"Joe", "Pets":[{"name":"spot", "species":"cat"}]}
>>> dd(d1, d2, "base")
Changes in base
Changes in Pets
Changes in 0
species changed in d2 to cat
Done with changes in 0
Done with changes in Pets
Done with changes in base

请注意,这将按索引对索引进行比较,因此需要进行一些修改才能很好地适用于添加或删除的列表项。

2020-12-20