2014-11-24 50 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']}}