我有两本词典,我想做的事情有点奇怪。基本上,我想合并它们。这很简单。但是它们是字典的层次结构,我想以这样的方式合并它们:如果字典中的项本身就是字典并且存在于两者中,我也希望合并这些字典。如果它不是字典,我希望第二个字典中的值覆盖第一个字典中的值。有点像这样:
a = {0: {0: "a"},
1: [0, 1, 2]}
b = {0: {1: "b"},
1: [3, 4, 5]}
Merge(a, b)
#output:
{0: {0: "a",
1: "b"},
1: [3, 4, 5]}
这有意义吗?因为关键" 0"在a和b中都包含一个字典,它也合并了那些字典。但是在第二个键的情况下,它是一个列表,所以它只是覆盖了它。
所以我想我会看某种递归函数?不太清楚如何处理这个问题。
谢谢!
编辑:我忘了提一个非常重要的细节:
我需要一个适用于2.6.2和2.7.3的功能。
答案 0 :(得分:1)
假设您可能有嵌套字典(基于您在递归方面的想法),这样的事情应该有效,
from copy import deepcopy
def merge(a, b):
if isinstance(b, dict) and isinstance(a, dict):
a_and_b = a.viewkeys() & b.viewkeys()
every_key = a.viewkeys() | b.viewkeys()
return {k: merge(a[k], b[k]) if k in a_and_b else
deepcopy(a[k] if k in a else b[k]) for k in every_key}
return deepcopy(b)
merge(a, b)
的返回值在概念上就像创建a
的(深层)副本并运行递归版a.update(b)
。
使用一些嵌套示例,
a = {0: {0: 'a'},
1: [0, 1, 2],
2: [9, 9],
3: {'a': {1: 1, 2: 2}, 'b': [0, 1]}}
b = {0: {1: 'b'},
1: [3, 4, 5],
2: {22: 22, 33: 33},
3: {'a': {2: 22, 3: 33}, 'b': [99, 88]}}
merge(a, b)
生成,
{0: {0: 'a', 1: 'b'},
1: [3, 4, 5],
2: {22: 22, 33: 33},
3: {'a': {1: 1, 2: 22, 3: 33}, 'b': [99, 88]}}
编辑:Python 2.6版
def merge(a, b):
if isinstance(b, dict) and isinstance(a, dict):
a_and_b = set(a).intersection(b)
every_key = set(a).union(b)
return dict((k, merge(a[k], b[k]) if k in a_and_b else
deepcopy(a[k] if k in a else b[k])) for k in every_key)
return deepcopy(b)
答案 1 :(得分:0)
嗯..只要你没有任意嵌套,你就不需要递归。
from itertools import chain
{k:(v if not isinstance(v,dict) else dict(chain(a[k].items(), v.items()))) for k,v in b.items()}
Out[10]: {0: {0: 'a', 1: 'b'}, 1: [3, 4, 5]}
(我在这里使用python 3,随意在python 2中用.items
替换.iteritems
由于这有点冗长,因此总是采用偷偷摸摸的方式合并两个词:
{k:(v if not isinstance(v,dict) else dict(a[k], **v)) for k,v in b.items()}
Out[11]: {0: {0: 'a', 1: 'b'}, 1: [3, 4, 5]}
您可能想也可能不想使用这种语法 - 尽管它很紧凑,但它有点滥用cPython实现细节。
答案 2 :(得分:0)
需要类似的东西并实现更简单的递归解决方案。就地更新dict' d'。
from Collections import MutableMapping
def merge(d, v):
"""
Merge two dictionaries.
Merge dict-like `v` into dict-like `d`. In case keys between them are the same, merge
their sub-dictionaries where possible. Otherwise, values in `v` overwrite `d`.
"""
for key in v:
if key in d and isinstance(d[key], MutableMapping) and isinstance(v[key], MutableMapping):
d[key] = merge(d[key], v[key])
else:
d[key] = v[key]
return d
示例1:
a = {0: {0: "a"},
1: [0, 1, 2]}
b = {0: {1: "b"},
1: [3, 4, 5]}
>>> merge(a, b)
{0: {0: 'a', 1: 'b'}, 1: [3, 4, 5]}
示例2:
a = {0: {0: 'a'},
1: [0, 1, 2],
2: [9, 9],
3: {'a': {1: 1, 2: 2}, 'b': [0, 1]}}
b = {0: {1: 'b'},
1: [3, 4, 5],
2: {22: 22, 33: 33},
3: {'a': {2: 22, 3: 33}, 'b': [99, 88]}}
>>> merge(a, b)
{0: {0: 'a', 1: 'b'},
1: [3, 4, 5],
2: {22: 22, 33: 33},
3: {'a': {1: 1, 2: 22, 3: 33}, 'b': [99, 88]}}