我有两个像:
x = {2: {'a':1, 'b':1}}
y = {3: {'a':1}, 2: {'a':2, 'c':2}}
我想要的合并结果应该是:
z = {3: {'a':1}, 2: {'a':3, 'b':1, 'c':2}}
我尝试了dict(x.items() + y.items())
和Counter
,但只获得了
{2: {'a': 2, 'c': 2}, 3: {'a': 1}}
结果。
如何合并dict,其值也是dict本身?
我已经解释过How to merge two Python dictionaries in a single expression?之间的区别 是我的dict的价值也是一个字典。
答案 0 :(得分:1)
这个怎么样:
对于Python2.x:
from collections import Counter
y = {2: {'a': 1, 'b': 1}, 1: {'a': 1, 'b': 1}}
x = {3: {'a': 1}, 2: {'a': 2, 'c': 2}}
t=x.copy()
print(dict({k: (dict(Counter(t.pop(k, None)) + Counter(v))) for k, v in y.items()},**t))
结果:
{1: {'a': 1, 'b': 1}, 2: {'a': 3, 'c': 2, 'b': 1}, 3: {'a': 1}}
对于Python3.5 +:
{**{k: (dict(Counter(t.pop(k, None)) + Counter(v))) for k, v in y.items()},**t}
答案 1 :(得分:0)
这里有一个可能的解决方案。虽然它不使用任何库,但它非常复杂。
它也适用于任何两个词典,独立于哪个词典。
{key: {ikey: x.get(key, {}).get(ikey, 0) + y.get(key, {}).get(ikey, 0)
for ikey in x.get(key, {}).keys()+y.get(key, {}).keys()}
for key in x.keys()+y.keys()}
<强>输出:强>
{2: {'a': 3, 'b': 1, 'c': 2}, 3: {'a': 1}}
答案 2 :(得分:0)
使用collections.Counter
来&#34;合并&#34;你想要合并的项目(只有公共密钥),并在dict理解中使用双三元表达式保留其他项目,迭代键的并集:
import collections
x = {2: {'a':1, 'b':1}}
y = {3: {'a':1}, 2: {'a':2, 'c':2}}
# pre-compute common keys, one-liners are not the ultimate goal in life!
common_keys = set(x) & set(y)
# now generate the merged dict
result = {k:collections.Counter(x[k])+collections.Counter(y[k]) if k in common_keys else x[k] if k in x else y[k] for k in set(x)|set(y)}
print(result)
结果:
{2: Counter({'a': 3, 'c': 2, 'b': 1}), 3: {'a': 1}}
注意:我们可以通过替换:
来避免事先计算公共密钥if k in common_keys
通过
if k in x and k in y
答案 3 :(得分:0)
假设对于某个键的任何相同深度,在两个dicts中值是相同类型(dict或两个数字,我不知道如何定义将数字合并到dict中)。
def merge(d1, d2):
for i in d2:
if i not in d1:
continue
if isinstance(d1[i], dict) and isinstance(d2[i], dict):
merge(d1[i], d2[i])
else:
d2[i] += d1[i]
d1.pop(i)
for j in d1:
d2[j] = d1[j]
它很简单但也许不优雅。
答案 4 :(得分:0)
这有效:
x = {2: {'a':1, 'b':1}}
y = {3: {'a':1}, 2: {'a':2, 'c':2}}
def key_merge (dict1, dict2):
## function which checks for any matching keys, and merges them
if len(dict1.keys()) == 0 or len(dict2.keys()) == 0:
return {}
else:
for key in dict1.keys():
if key in dict2.keys():
return {key:{ k: dict1[key].get(k, 0) + dict2[key].get(k, 0) for k in set(dict1[key])|set(dict2[key]) }}
z = {**x, **y, **key_merge(x, y)}
再次,如果它优雅的话,由你决定!
答案 5 :(得分:0)
我不知道你对'优雅'的定义是什么,但假设你的意思是可读的,那么也许这种方式适合你。
from collections import Counter
def counter_dict(in_dict):
"""
Create a dict of Counters from a dict of dicts.
"""
return dict((k, Counter(v)) for (k, v) in in_dict.items())
def merge_counter_dicts(a, b):
"""
Create a dict of Counters from two dicts of Counters.
Where keys exist in both counts are summed.
"""
out_dict = a.copy()
for k in b.keys():
out_dict[k] = out_dict.setdefault(k, Counter()) + b[k]
return out_dict
x = {2: {'a': 1, 'b': 1}}
y = {3: {'a': 1}, 2: {'a': 2, 'c': 2}}
xc = counter_dict(x)
xy = counter_dict(y)
print merge_counter_dicts(xc, xy)
答案 6 :(得分:0)
# What about something like this:
# merge_nested_dicts.py
# tested under Python3.6
# assuming dict_02 overwrites dict_01
# one liner functional style
def deep_merge(dict_01, dict_02):
return {k: {**dict_01.get(k), **dict_02.get(k)} if k in dict_01 and
isinstance(dict_01.get(k), dict) and
isinstance(dict_02.get(k), dict) else v
for k, v in {**dict_01, **dict_02}.items()}
if __name__ == '__main__':
y = {2: {'a': 1, 'b': 1}, 1: {'a': 1, 'b': 1}}
x = {3: {'a': 1}, 2: {'a': 2, 'c': 2}}
print(x)
print(y)
print(deep_merge(x, y))
'''
{3: {'a': 1}, 2: {'a': 2, 'c': 2}}
{2: {'a': 1, 'b': 1}, 1: {'a': 1, 'b': 1}}
{3: {'a': 1}, 2: {'a': 1, 'c': 2, 'b': 1}, 1: {'a': 1, 'b': 1}}
'''