字典的字典合并
尽管存在某些非通用情况,但这是规范问题,我提供了解决此问题的Pythonic方法。
最简单的情况:“嵌套的字典以空字典结尾”:
d1 = {'a': {1: {'foo': {}}, 2: {}}}
d2 = {'a': {1: {}, 2: {'bar': {}}}}
d3 = {'b': {3: {'baz': {}}}}
d4 = {'a': {1: {'quux': {}}}}
这是递归最简单的情况,我会推荐两个比较朴素的方法:
def rec_merge1(d1, d2):
'''return new merged dict of dicts'''
for k, v in d1.items():
if k in d2:
d2[k] = rec_merge1(v, d2[k])
d3 = d1.copy()
d3.update(d2)
return d3
def rec_merge2(d1, d2):
'''update first dict with second recursively'''
for k, v in d1.items():
if k in d2:
d2[k] = rec_merge2(v, d2[k])
d1.update(d2)
return d1
我相信我更喜欢第二个而不是第一个,但请记住第一个的原始状态必须从其起源重新构建。以下是用法:
>>> from functools import reduce # only required for Python 3.
>>> reduce(rec_merge1, (d1, d2, d3, d4))
{'a': {1: {'quux': {}, 'foo': {}}, 2: {'bar': {}}}, 'b': {3: {'baz': {}}}}
>>> reduce(rec_merge2, (d1, d2, d3, d4))
{'a': {1: {'quux': {}, 'foo': {}}, 2: {'bar': {}}}, 'b': {3: {'baz': {}}}}
复杂情况:“叶子节点为任何其他类型:”
如果它们以字典结尾,则将结束的空字典合并是一个简单的情况。如果不是,则不太容易。如果是字符串,如何合并它们?集合可以类似地更新,因此我们可以给予相同的处理,但我们会失去它们合并的顺序。那么顺序重要吗?
因此,在缺乏更多信息的情况下,如果两个值都不是字典,则最简单的方法是为它们提供标准的更新处理:即第二个字典的值将覆盖第一个字典的值,即使第二个字典的值为None而第一个字典的值具有大量信息。
d1 = {'a': {1: 'foo', 2: None}}
d2 = {'a': {1: None, 2: 'bar'}}
d3 = {'b': {3: 'baz'}}
d4 = {'a': {1: 'quux'}}
from collections.abc import MutableMapping
def rec_merge(d1, d2):
'''
Update two dicts of dicts recursively,
if either mapping has leaves that are non-dicts,
the second's leaf overwrites the first's.
'''
for k, v in d1.items():
if k in d2:
if all(isinstance(e, MutableMapping) for e in (v, d2[k])):
d2[k] = rec_merge(v, d2[k])
d3 = d1.copy()
d3.update(d2)
return d3
现在
from functools import reduce
reduce(rec_merge, (d1, d2, d3, d4))
返回
{'a': {1: 'quux', 2: 'bar'}, 'b': {3: 'baz'}}
原问题的应用:
为了使 Python 代码合法(否则在 Python 2.7+ 中它们将成为集合字面量),我已经删除了字母周围的花括号并将它们放在单引号中,同时添加了一个缺失的大括号:
dict1 = {1:{"a":'A'}, 2:{"b":'B'}}
dict2 = {2:{"c":'C'}, 3:{"d":'D'}}
现在,rec_merge(dict1, dict2)
返回:
{1: {'a': 'A'}, 2: {'c': 'C', 'b': 'B'}, 3: {'d': 'D'}}
将原问题的期望结果与更改后的结果进行匹配(例如将{A}
更改为'A'
)。
d = Dict({1:{"a":{'A'}}, 2:{"b":{'B'}}}); d.update({2:{"c":{'C'}}, 3:{"d":{'D'}}}); d
=>{1: {'a': {'A'}}, 2: {'b': {'B'}, 'c': {'C'}}, 3: {'d': {'D'}}}
- bartolo-otrit