合并字典与子字典
Merge dictionaries with sub dictionaries
我想深度合并 2 个词典,它们在某种程度上都具有一个或多个具有相同键的词典值。我怎样才能简单地合并那些内部词典?类似于“**”符号但深度合并。
示例:
d1 = {"v1": "value1", "sub": {"sv1": "sub value 1"}}
d2 = {"v2": "value2", "sub": {"sv2": "sub value 2"}}
d3 = {**d1, **d2}
print(d3)
实际结果:
{'v1': 'value1', 'sub': {'sv2': 'sub value 2'}, 'v2': 'value2'}
想要的结果:
{'v1': 'value1',
'sub': {'sv1': 'sub value 1', 'sv2': 'sub value 2'},
'v2': 'value2'}
注意到 sub -> sv1 -> 子值 1
这是一个简单的例子,实际案例中还有多几层字典。此外,解决方案需要通用,因为字典的结构事先未知。
您已经完成了使用所有常用键创建 d3 的前三个步骤:
>>> d1 = {"v1": "value1", "sub": {"sv1": "sub value 1"}}
>>> d2 = {"v2": "value2", "sub": {"sv2": "sub value 2"}}
>>> d3 = {**d1, **d2} # initial merge of common keys
只需要一个后续步骤来合并所有 "sub" 条目:
>>> for d in (d1, d2): # merge the "sub" entries
d3['sub'].update(d['sub'])
给出了想要的结果:
>>> d3
{'v1': 'value1', 'sub': {'sv2': 'sub value 2', 'sv1': 'sub value 1'}, 'v2': 'value2'}
希望这对您有所帮助:-)
对于 python3:
d1 = {"v1": "value1", "sub": {"sv1": "sub value 1",'newsub':"value 2",'newsubdict':{'ok':'pssible','not_again':{'key1':'just checking'}}}}
d2 = {"v2": "value2", "sub": {"sv2": "sub value 2",'newsubdict':{'fine':'i am working','not_again':{'key2':'Am i right?'}}}}
from copy import deepcopy
d3 = deepcopy(d1)
def combine_key(d2,d3):
for key in d2.keys():
if(key in d3):
d3[key] =d2[key]
elif(isinstance(d3[key],dict)):
combine_key(d2[key],d3[key])
else:
d3[key].update(d2[key])
combine_key(d2,d3)
print(d3) #{'v1': 'value1', 'sub': {'sv1': 'sub value 1', 'newsub': 'value 2', 'newsubdict': {'ok': 'pssible', 'not_again': {'key1': 'just checking', 'key2': 'Am i right?'}, 'fine': 'i am working'}, 'sv2': 'sub value 2'}, 'v2': 'value2'}
我最后写了这个:
import collections
import copy
def deep_dict_merge(dct1, dct2, override=True) -> dict:
"""
:param dct1: First dict to merge
:param dct2: Second dict to merge
:param override: if same key exists in both dictionaries, should override? otherwise ignore. (default=True)
:return: The merge dictionary
"""
merged = copy.deepcopy(dct1)
for k, v2 in dct2.items():
if k in merged:
v1 = merged[k]
if isinstance(v1, dict) and isinstance(v2, collections.Mapping):
merged[k] = deep_dict_merge(v1, v2, override)
elif isinstance(v1, list) and isinstance(v2, list):
merged[k] = v1 + v2
else:
if override:
merged[k] = copy.deepcopy(v2)
else:
merged[k] = copy.deepcopy(v2)
return merged
我想深度合并 2 个词典,它们在某种程度上都具有一个或多个具有相同键的词典值。我怎样才能简单地合并那些内部词典?类似于“**”符号但深度合并。
示例:
d1 = {"v1": "value1", "sub": {"sv1": "sub value 1"}}
d2 = {"v2": "value2", "sub": {"sv2": "sub value 2"}}
d3 = {**d1, **d2}
print(d3)
实际结果:
{'v1': 'value1', 'sub': {'sv2': 'sub value 2'}, 'v2': 'value2'}
想要的结果:
{'v1': 'value1',
'sub': {'sv1': 'sub value 1', 'sv2': 'sub value 2'},
'v2': 'value2'}
注意到 sub -> sv1 -> 子值 1
这是一个简单的例子,实际案例中还有多几层字典。此外,解决方案需要通用,因为字典的结构事先未知。
您已经完成了使用所有常用键创建 d3 的前三个步骤:
>>> d1 = {"v1": "value1", "sub": {"sv1": "sub value 1"}}
>>> d2 = {"v2": "value2", "sub": {"sv2": "sub value 2"}}
>>> d3 = {**d1, **d2} # initial merge of common keys
只需要一个后续步骤来合并所有 "sub" 条目:
>>> for d in (d1, d2): # merge the "sub" entries
d3['sub'].update(d['sub'])
给出了想要的结果:
>>> d3
{'v1': 'value1', 'sub': {'sv2': 'sub value 2', 'sv1': 'sub value 1'}, 'v2': 'value2'}
希望这对您有所帮助:-)
对于 python3:
d1 = {"v1": "value1", "sub": {"sv1": "sub value 1",'newsub':"value 2",'newsubdict':{'ok':'pssible','not_again':{'key1':'just checking'}}}}
d2 = {"v2": "value2", "sub": {"sv2": "sub value 2",'newsubdict':{'fine':'i am working','not_again':{'key2':'Am i right?'}}}}
from copy import deepcopy
d3 = deepcopy(d1)
def combine_key(d2,d3):
for key in d2.keys():
if(key in d3):
d3[key] =d2[key]
elif(isinstance(d3[key],dict)):
combine_key(d2[key],d3[key])
else:
d3[key].update(d2[key])
combine_key(d2,d3)
print(d3) #{'v1': 'value1', 'sub': {'sv1': 'sub value 1', 'newsub': 'value 2', 'newsubdict': {'ok': 'pssible', 'not_again': {'key1': 'just checking', 'key2': 'Am i right?'}, 'fine': 'i am working'}, 'sv2': 'sub value 2'}, 'v2': 'value2'}
我最后写了这个:
import collections
import copy
def deep_dict_merge(dct1, dct2, override=True) -> dict:
"""
:param dct1: First dict to merge
:param dct2: Second dict to merge
:param override: if same key exists in both dictionaries, should override? otherwise ignore. (default=True)
:return: The merge dictionary
"""
merged = copy.deepcopy(dct1)
for k, v2 in dct2.items():
if k in merged:
v1 = merged[k]
if isinstance(v1, dict) and isinstance(v2, collections.Mapping):
merged[k] = deep_dict_merge(v1, v2, override)
elif isinstance(v1, list) and isinstance(v2, list):
merged[k] = v1 + v2
else:
if override:
merged[k] = copy.deepcopy(v2)
else:
merged[k] = copy.deepcopy(v2)
return merged