在python中合并具有相似键的字典


data1 = {'Height': {'Ajay': 145.830651784016,
'Bist': 145.91779226416696,
'Kay': 146.16402145150246}
}

data2 = {'Height': {'Kim': 155.830651784016,
'DDD': 155.91779226416696,
'Arambh': 156.16402145150246}
}
data3 = {'Height': {'Dong': 165.830651784016,
'Ding': 165.91779226416696,
'Dumba': 166.16402145150246}
}

以上是我希望合并成一个的3本字典。以下是预期输出:

den_w = {'Height': {'Ajay': 145.830651784016,
'Bist': 145.91779226416696,
'Kay': 146.16402145150246,
'Kim': 155.830651784016,
'DDD': 155.91779226416696,
'Arambh': 156.16402145150246,
'Dong': 165.830651784016,
'Ding': 165.91779226416696,
'Dumba': 166.16402145150246}
}

下面是我的尝试。未达到预期输出:

失败尝试1:

den_w = {**data1, **data2, **data3}

尝试失败2:

den_w = {k: [data1.get(k, {}), data2.get(k, {}), data3.get(k, {})] for k in data1.keys() | data2.keys() | data3.keys()}

失败尝试3:

dicts = data1,data2,data3

失败尝试4:

dicts = {}
dicts.update(data1)
dicts.update(data2)
dicts.update(data3)

任何达到预期输出的方法

EDIT:仅使用ChainMap的方法

下面是一个单行代码。它对字典中每个唯一键的子字典进行分组和组合。

from collections import ChainMap
L = [data1, data2, data3]
{k:dict(ChainMap(*[i.get(k) for i in L])) for k in dict(ChainMap(*L)).keys()}
{'Height': {'Dong': 165.830651784016,
'Ding': 165.91779226416696,
'Dumba': 166.16402145150246,
'Kim': 155.830651784016,
'DDD': 155.91779226416696,
'Arambh': 156.16402145150246,
'Ajay': 145.830651784016,
'Bist': 145.91779226416696,
'Kay': 146.16402145150246}}

在演示案例上测试-

d1 = {'a':{'x':1, 'y':2}, 'b':{'l':1, 'm':2}}
d2 = {'a':{'i':1, 'j':2}, 'b':{'w':1, 'z':2}}
L = [d1, d2]
{k:dict(ChainMap(*[i.get(k) for i in L])) for k in dict(ChainMap(*L)).keys()}
#dictionaries for key a and b are respectively combined
{'a': {'i': 1, 'j': 2, 'x': 1, 'y': 2}, 
'b': {'w': 1, 'z': 2, 'l': 1, 'm': 2}}

下面是使用collections.defaultdictcollections.ChainMap的python方法。我已经解释了下面的步骤。

from collections import ChainMap, defaultdict
L = [data1, data2, data3]
d = defaultdict(dict)
for key in dict(ChainMap(*L)).keys():
for i in L:
d[key].update(i.get(key))
d = dict(d)
print(d)
{'Height': {'Dong': 165.830651784016,
'Ding': 165.91779226416696,
'Dumba': 166.16402145150246,
'Kim': 155.830651784016,
'DDD': 155.91779226416696,
'Arambh': 156.16402145150246,
'Ajay': 145.830651784016,
'Bist': 145.91779226416696,
'Kay': 146.16402145150246}}
  1. defaultdict(dict)存储字典的字典
  2. dict(ChainMap(*L)).keys()获取存在于列表中所有字典中的唯一键。本例中为height
  3. 对于每个key和列表中的每个元素,键的字典用该key的值更新。
  4. 将此d转换为dict

试试这个:

def merge(a, b):
for key in b:
if key in a:
if isinstance(a[key], dict) and isinstance(b[key], dict):
merge(a[key], b[key])
elif a[key] == b[key]:
pass             
else:
a[key] = b[key]
return a
den_w  = merge(data1, data2)
den_w = merge(den_w, data3)

输出:

{'Height': {'Ajay': 145.830651784016,
'Arambh': 156.16402145150246,
'Bist': 145.91779226416696,
'DDD': 155.91779226416696,
'Ding': 165.91779226416696,
'Dong': 165.830651784016,
'Dumba': 166.16402145150246,
'Kay': 146.16402145150246,
'Kim': 155.830651784016}}

找到所有字典之间的公共键,然后合并它们

{k: {**data1[k], **data2[k], **data3[k]} 
for k in set(data1.keys()).intersection(
set(data2.keys())).intersection(set(data3.keys()))}

输出:

{'Height': {'Ajay': 145.830651784016,
'Arambh': 156.16402145150246,
'Bist': 145.91779226416696,
'DDD': 155.91779226416696,
'Ding': 165.91779226416696,
'Dong': 165.830651784016,
'Dumba': 166.16402145150246,
'Kay': 146.16402145150246,
'Kim': 155.830651784016}}

update方法合并字典,例如

dicts = {}
dicts.update(data1)
dicts.update(data2)
dicts.update(data3)

这将用数据的并集创建一个新字典(正如人们所期望的那样,以后的更新将取代以前的更新)。这就是所谓的"浅"。合并,即它只合并顶级键。

要合并整个键树,问题就变得不平凡了,有很多不同的方法来解释深度合并。deepmerge包实现了其中的一些策略,例如

dicts = {}
merge_strategy.merge(dicts, data1)

如果您不需要一个完全通用的解决方案,下面的方法可能就足够了:

data1 = {'Height': {'Ajay': 145.830651784016,
'Bist': 145.91779226416696,
'Kay': 146.16402145150246}
}

data2 = {'Height': {'Kim': 155.830651784016,
'DDD': 155.91779226416696,
'Arambh': 156.16402145150246}
}
data3 = {'Height': {'Dong': 165.830651784016,
'Ding': 165.91779226416696,
'Dumba': 166.16402145150246}
}
den_w = data1.copy() 
den_w['Height'].update(data2['Height'])
den_w['Height'].update(data3['Height'])
print(den_w)

给你:

{'Height': {'Ajay': 145.830651784016,
'Bist': 145.91779226416696,
'Kay': 146.16402145150246,
'Kim': 155.830651784016,
'DDD': 155.91779226416696,
'Arambh': 156.16402145150246,
'Dong': 165.830651784016,
'Ding': 165.91779226416696,
'Dumba': 166.16402145150246}
}

如果你使用的是Python 3.9,也可以是:

den_w = data1.copy() 
den_w['Height'] |= data2['Height'] | data3['Height']

最新更新