2014-11-24 49 views
-1

我正在努力解决递归合并问题。合并字典数组中的重复项

比方说,我有:

a=[{'name':"bob", 
    'age':10, 
    'email':"[email protected]", 
    'profile':{'id':1, 'role':"admin"}}, 
    {'name':"bob", 
    'age':10, 
    'email':"other mail", 
    'profile':{'id':2, 'role':"dba"}, 
    'home':"/home/bob" 
    }] 

,我需要一些东西来递归合并条目。如果同一级别上的现有给定键的值不同,它会将该值附加到数组。

b = merge(a) 
print b 
{'name':"bob", 
'age':10, 
'email':["[email protected]","other mail"], 
'profile':{'id':[1,2], 'role'=["admin", "dba"], 'home':"/home/bob"} 

我写了这个代码:

def merge(items): 
    merged = {} 
    for item in items: 
     for key in item.keys(): 
      if key in merged.keys(): 
       if item[key] != merged[key]: 
        if not isinstance(merged[key], list): 
         merged[key] = [merged[key]] 
        if item[key] not in merged[key]: 
         merged[key].append(item[key]) 
      else: 
       merged[key] = item[key] 
    return merged 

输出是:

{'age': 10, 
'email': ['[email protected]', 'other mail'], 
'home': '/home/bob', 
'name': 'bob', 
'profile': [{'id': 1, 'role': 'admin'}, {'id': 2, 'role': 'dba'}]} 

这是不是我想要的。

我无法弄清楚如何处理递归。

谢谢:)

+0

哪里是你的代码,究竟是它的问题? – jonrsharpe 2014-11-24 17:25:36

+0

正如我所说,我正在努力与这一个... – CyrilPeponnet 2014-11-24 17:28:13

+0

所以你有...什么都没有?这不是一个代码写入服务。 – jonrsharpe 2014-11-24 17:28:51

回答

0

当你遍历每个字典中的参数,然后在每个字典中的每个键和值,你要下列规则:

  1. 如果没有针对关键在什么输出,将新的键和值添加到输出;
  2. 如果该键有一个值,并且与新值相同,则什么都不做;
  3. 如果该键有值,并且是列表append列表的新值;
  4. 如果该键有一个值,它是一个字典,递归merge现有字典的新值;
  5. 如果该键有一个值,它既不是一个列表也不是一个字典,请将输出中的值设置为当前值和新值的列表。

在代码:

def merge(*dicts): 
    """Recursively merge the argument dictionaries.""" 
    out = {} 
    for dct in dicts: 
     for key, val in dct.items(): 
      try: 
       out[key].append(val) # 3. 
      except AttributeError: 
       if out[key] == val: 
        pass # 2. 
       elif isinstance(out[key], dict): 
        out[key] = merge(out[key], val) # 4. 
       else: 
        out[key] = [out[key], val] # 5. 
      except KeyError: 
       out[key] = val # 1. 
    return out 

在使用中:

>>> import pprint 
>>> pprint.pprint(merge(*a)) 
{'age': 10, 
'email': ['[email protected]', 'other mail'], 
'home': '/home/bob', 
'name': 'bob', 
'profile': {'id': [1, 2], 'role': ['admin', 'dba']}}