数组友好的字典合并

时间:2017-09-22 15:44:52

标签: python dictionary

我有两个字典可能格式如下:

d1 = { "root" : { "leaf" : [diff1, diff2] }}

d2 = { "root" : { "leaf": [diff3], "node": { "leaf" : [diff1] } } }

我希望能够将它们组合成这样的结果:

d3 = {'root': {'leaf': ['diff1', 'diff2', 'diff 3'], 'node': {'leaf': ['diff 1']}}}

对于任何给定的输入,递归级别是未定义的,但是每个“叶子节点”将是一个数组,如果每个字典中的叶节点存在一个数组,我想组合它。注意:键实际上不是“节点”和“叶子”,我只是使用这些键来帮助说明示例。

这段代码似乎用第二个完全覆盖了我的数组: d3 = {**d1, **d2}屈服 result = {'root': {'leaf': ['diff 3'], 'node': {'leaf': ['diff 1']}}}

2 个答案:

答案 0 :(得分:1)

未经测试,但这样的事情应该有效:

def dictmerge(d1, d2):
    if d1 is None:
        return d2
    if d2 is None:
        return d1
    if isinstance(d1, list) and isinstance(d2, list):
        return d1+d2
    if isinstance(d1, dict) and isinstance(d2, dict):
        return {k: dictmerge(d1.get(k), d2.get(k))
            for k in set(d1.keys()) | set(d2.keys())}
    raise ValueError, "inputs have incompatible structure"

答案 1 :(得分:1)

您可以使用递归函数执行此操作。请注意,这只会合并列表,而不是元组或任何其他类型的序列:

def merge_dicts(d1, d2):
    out_dict = {}
    for key in (set(d1.keys()) | set(d2.keys())):
        if key in d1 and key in d2:
            if isinstance(d1[key], dict) and isinstance(d2[key], dict):
                out_dict[key] = merge_dicts(d1[key], d2[key])
            elif isinstance(d1[key], list) and isinstance(d2[key], list):
                out_dict[key] = d1[key] + d2[key]
            elif d1[key] == d2[key]:
                out_dict[key] = d1[key]
            else:
                raise ValueError(
                    'Cannot merge conflicting values {} and {}'.format(
                        d1[key], d2[key]))
        elif key in d1:
            out_dict[key] = d1[key]
        else:
            out_dict[key] = d2[key]
    return out_dict

d1 = { "root" : { "leaf" : ['diff1', 'diff2'] }}
d2 = { "root" : { "leaf": ['diff3'], "node": { "leaf" : ['diff1'] } } }

print(merge_dicts(d1, d2))

如果您拨打merge_dicts({'key': 'value'}, {'key': 'different_value'}),则尚未定义要执行的操作。我有它提出一个ValueError,因为我认为你不能合并这两个dicts(你会采用哪个值?)但是你可以改变它,例如,如果你想从其中一个dicts中选择值作为默认值。