2011-06-06 219 views
1

有沒有簡單的方法來結合Python中的字典的兩個字典?這是我需要:結合詞典的兩個詞典(Python)

dict1 = {'A' : {'B' : 'C'}} 
dict2 = {'A' : {'D' : 'E'}} 

result = dict_union(dict1, dict2) 
# => result = {'A' : {'B' : 'C', 'D' : 'E'}} 

我創建了一個強力功能做的,但我一直在尋找一個更緊湊的解決方案:

def dict_union(train, wagon): 
    for key, val in wagon.iteritems(): 
     if not isinstance(val, dict): 
      train[key] = val 
     else: 
      subdict = train.setdefault(key, {}) 
      dict_union(subdict, val) 
+5

這不是一個'dict'結合。 – 2011-06-06 18:12:59

+4

我不清楚你在結構不匹配時想要發生什麼。例如,如果dict3 = {'A':'F'},那麼在這裏使用你的版本,dict_union(dict3,dict2)會拋出一個TypeError。這是期望的行爲? – Cosmologicon 2011-06-06 18:25:21

+0

相關(但更簡單):http://stackoverflow.com/questions/1031199/adding-dictionaries-in-python – Gilles 2012-01-17 13:29:05

回答

0

你可以繼承dict,敷原dict.update()方法與一個版本,這將調用update()在subdicts而不是直接覆蓋subdicts。儘管如此,這最終可能會比現有的解決方案花費更多的精力。

+0

是的,但你需要確保正在更新的字典中的任何字典也是你的子類。 – Cosmologicon 2011-06-06 18:14:42

0

必須是遞歸的,因爲字典可以嵌套。這是我第一次接觸它,你可能想要定義你的行爲,當字典嵌套在不同的深度。

def join(A, B): 
    if not isinstance(A, dict) or not isinstance(B, dict): 
     return A or B 
    return dict([(a, join(A.get(a), B.get(a))) for a in set(A.keys()) | set(B.keys())]) 

def main(): 
    A = {'A': {'B': 'C'}, 'D': {'X': 'Y'}} 
    B = {'A': {'D': 'E'}} 
    print join(A, B) 
+0

從參數{'A':{'B':'C'}}和{'A':'F'}的OP函數返回不同的結果。不過,我不確定OP是否已經考慮過這個例子。 – Cosmologicon 2011-06-06 18:43:44

+1

是啊,你說得對,這就是我說的關於當字跡深度不同時的行爲。你必須定義你自己的。我只是返回第一個非None或A或B的。你可以做'B或A',這是他的代碼所做的,或者其他任何衝突解決方案。 – 2011-06-06 18:53:50

3

該解決方案非常緊湊。它的醜陋,但你問一些相當複雜的行爲:

dict_union = lambda d1,d2: dict((x,(dict_union(d1.get(x,{}),d2[x]) if 
    isinstance(d2.get(x),dict) else d2.get(x,d1.get(x)))) for x in 
    set(d1.keys()+d2.keys())) 
0

至於我沒有enaugh信息,但無論如何請在下面找到我的示例代碼:

dict1 = {'A' : {'B' : 'C'}} 
dict2 = {'A' : {'D' : 'E'}, 'B':{'C':'D'}} 
output = {} 
for key in (set(dict1) | set(dict2): 
    output[key] = {} 
    (key in dict1 and output[key].update(dict1.get(key))) 
    (key in dict2 and output[key].update(dict2.get(key))) 
4

這裏是一個類, RUDict(用於遞歸更新字典),實現您正在尋找的行爲:

class RUDict(dict): 

    def __init__(self, *args, **kw): 
     super(RUDict,self).__init__(*args, **kw) 

    def update(self, E=None, **F): 
     if E is not None: 
      if 'keys' in dir(E) and callable(getattr(E, 'keys')): 
       for k in E: 
        if k in self: # existing ...must recurse into both sides 
         self.r_update(k, E) 
        else: # doesn't currently exist, just update 
         self[k] = E[k] 
      else: 
       for (k, v) in E: 
        self.r_update(k, {k:v}) 

     for k in F: 
      self.r_update(k, {k:F[k]}) 

    def r_update(self, key, other_dict): 
     if isinstance(self[key], dict) and isinstance(other_dict[key], dict): 
      od = RUDict(self[key]) 
      nd = other_dict[key] 
      od.update(nd) 
      self[key] = od 
     else: 
      self[key] = other_dict[key] 


def test(): 
    dict1 = {'A' : {'B' : 'C'}} 
    dict2 = {'A' : {'D' : 'E'}} 

    dx = RUDict(dict1) 
    dx.update(dict2) 
    print(dx) 


if __name__ == '__main__': 
    test() 


>>> import RUDict 
>>> RUDict.test() 
{'A': {'B': 'C', 'D': 'E'}} 
>>>