如何合并复杂的嵌套字典

时间:2018-03-21 18:48:56

标签: python dictionary

我有两本词典:

dict1 = {'cm': {'fill': {'user': {'registration': {'flag': 'f'}}}}}
dict2 = {'cm': {'fill': {'user': {'url': 'www.example.com'}}}}

我想要的输出:

dict3 = {'cm': {'fill': {'user':{'registration': {'flag': 'f'}}, {'url': 'www.example.com'}}}

这是我到目前为止所尝试的内容:

dict3 = {**dict1, **dict2} # This does not work. It only gives me a `dict1`.

问题是dict1dict2可以有很多嵌入式密钥。

知道怎么做吗?

3 个答案:

答案 0 :(得分:2)

正确:合并不会做你想要的。你有累积来做多个级别。我怀疑你得到你想要的最简单的方法 - 合并到未指定的(任意)深度 - 就是编写一个递归例程来进行你想要的合并。

def dict_merge(d1, d2):
    for key in d1:
        if key in d2:
            one_merge = dict_merge(d1[key], d2[key])
        else:
            one_merge = d1[key]
    for ... # also pick up keys in d2 that are not in d1.

我会告诉你是否用设置的交集和差异处理这个逻辑。

答案 1 :(得分:1)

如果字典的结构一致,则可以使用collections.defaultdict嵌套方法。

可以将嵌套的defaultdict转换为常规dict对象。但对于您的用例,这可能不是必需的。

from collections import defaultdict

dict1 = {'cm': {'fill': {'user': {'registration': {'flag': 'f'}}}}}
dict2 = {'cm': {'fill': {'user': {'url': 'www.example.com'}}}}

rec_dd = lambda: defaultdict(rec_dd)
d = rec_dd()

for i in [dict1, dict2]:
    d['cm']['fill']['user'].update(i['cm']['fill']['user'])

# defaultdict(<function __main__.<lambda>>,
#             {'cm': defaultdict(<function __main__.<lambda>>,
#                          {'fill': defaultdict(<function __main__.<lambda>>,
#                                       {'user': defaultdict(<function __main__.<lambda>>,
#                                                    {'registration': {'flag': 'f'},
#                                                     'url': 'www.example.com'})})})})

答案 2 :(得分:0)

您可以在zip数据时使用递归:

dict1 = {'cm': {'fill': {'user': {'registration': {'flag': 'f'}}}}}
dict2 = {'cm': {'fill': {'user': {'url': 'www.example.com'}}}}
def update_dict(d1, d2):
   return {a:update_dict(b, d) if a == c and list(b.keys())[0] == list(d.keys())[0] else {**b, **d} for [a, b], [c, d] in zip(d1.items(), d2.items())}

输出:

{'cm': {'fill': {'user': {'registration': {'flag': 'f'}, 'url': 'www.example.com'}}}}