2017-09-22 77 views
0

我有可能被格式化像下面两个字典:阵列型词典合并

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']}}}

回答

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

你可以用递归函数做到这一点。请注意,这只会合并列表,而不是元组或任何其他类型的序列:

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,因为我认为你不能合并这两个字节(你会采用哪个值?),但是如果你想从一个字典中选择一个值作为默认值,你可以改变它。