Словари слияния словарей - PullRequest
       68

Словари слияния словарей

98 голосов
/ 26 августа 2011

Мне нужно объединить несколько словарей, вот что у меня есть, например:

dict1 = {1:{"a":{A}}, 2:{"b":{B}}}

dict2 = {2:{"c":{C}}, 3:{"d":{D}}

С A B C и D листьями дерева, как {"info1":"value", "info2":"value2"}

Существует неизвестный уровень (глубина) словарей, это может быть {2:{"c":{"z":{"y":{C}}}}}

В моем случае это структура каталогов / файлов, в которой узлами являются документы, а файлами - файлы.

Я хочу объединить их, чтобы получить:

 dict3 = {1:{"a":{A}}, 2:{"b":{B},"c":{C}}, 3:{"d":{D}}}

Я не уверен, как я мог бы сделать это легко с Python.

Ответы [ 22 ]

0 голосов
/ 31 января 2014

Самый простой способ, о котором я могу думать, это:

#!/usr/bin/python

from copy import deepcopy
def dict_merge(a, b):
    if not isinstance(b, dict):
        return b
    result = deepcopy(a)
    for k, v in b.iteritems():
        if k in result and isinstance(result[k], dict):
                result[k] = dict_merge(result[k], v)
        else:
            result[k] = deepcopy(v)
    return result

a = {1:{"a":'A'}, 2:{"b":'B'}}
b = {2:{"c":'C'}, 3:{"d":'D'}}

print dict_merge(a,b)

Вывод:

{1: {'a': 'A'}, 2: {'c': 'C', 'b': 'B'}, 3: {'d': 'D'}}
0 голосов
/ 25 сентября 2014

У меня есть другое немного другое решение:

def deepMerge(d1, d2, inconflict = lambda v1,v2 : v2) :
''' merge d2 into d1. using inconflict function to resolve the leaf conflicts '''
    for k in d2:
        if k in d1 : 
            if isinstance(d1[k], dict) and isinstance(d2[k], dict) :
                deepMerge(d1[k], d2[k], inconflict)
            elif d1[k] != d2[k] :
                d1[k] = inconflict(d1[k], d2[k])
        else :
            d1[k] = d2[k]
    return d1

По умолчанию он разрешает конфликты в пользу значений из второго диктанта, но вы можете легко переопределить это, с помощью некоторого колдовства вы можете даже выбросить исключения из него. :.)

...