python - 递归合并字典,使具有共享键的元素组合成一个列表
问题描述
我有两个要合并的字典:
a = {"name": "john",
"phone":"123123123",
"owns": {"cars": "Car 1", "motorbikes": "Motorbike 1"}}
b = {"name": "john",
"phone":"123",
"owns": {"cars": "Car 2"}}
如果a
并且b
在同一嵌套级别上有一个公共键,则结果应该是一个列表,其中包含两个值,它被分配为共享键的值。
结果应如下所示:
{"name": "john",
"phone":["123123123","123"],
"owns": {"cars": ["Car 1", "Car 2"], "motorbikes": "Motorbike 1"}}
Usinga.update(b)
不起作用,因为它用 的共享值覆盖了a
的共享值b
,因此结果是这样的:
{'name': 'john', 'phone': '123', 'owns': {'cars': 'Car 2'}}
目标是在不覆盖的情况下合并字典,并保留与特定键相关的所有信息(在任一字典中)。
解决方案
通过递归,您可以构建一个字典理解来实现这一点。
此解决方案还考虑到您可能希望稍后合并两个以上的字典,从而在这种情况下展平值列表。
def update_merge(d1, d2):
if isinstance(d1, dict) and isinstance(d2, dict):
# Unwrap d1 and d2 in new dictionary to keep non-shared keys with **d1, **d2
# Next unwrap a dict that treats shared keys
# If two keys have an equal value, we take that value as new value
# If the values are not equal, we recursively merge them
return {
**d1, **d2,
**{k: d1[k] if d1[k] == d2[k] else update_merge(d1[k], d2[k])
for k in {*d1} & {*d2}}
}
else:
# This case happens when values are merged
# It bundle values in a list, making sure
# to flatten them if they are already lists
return [
*(d1 if isinstance(d1, list) else [d1]),
*(d2 if isinstance(d2, list) else [d2])
]
例子:
a = {"name": "john", "phone":"123123123",
"owns": {"cars": "Car 1", "motorbikes": "Motorbike 1"}}
b = {"name": "john", "phone":"123", "owns": {"cars": "Car 2"}}
update_merge(a, b)
# {'name': 'john',
# 'phone': ['123123123', '123'],
# 'owns': {'cars': ['Car 1', 'Car 2'], 'motorbikes': 'Motorbike 1'}}
合并两个以上对象的示例:
a = {"name": "john"}
b = {"name": "jack"}
c = {"name": "joe"}
d = update_merge(a, b)
d = update_merge(d, c)
d # {'name': ['john', 'jack', 'joe']}
推荐阅读
- reactjs - 材料表反应。如何使表格标题和标题具有粘性
- sonarqube - Sonarqube 找不到可能的空指针异常
- java - 在指定超时之前抛出异常“java.net.ConnectException:连接超时:连接”
- google-cloud-sql - 谷歌 SQL 查询 (MySQL)
- reactjs - 反应输入:在输入为空的情况下添加值
- vue.js - vue-bootstrap 不能在 sortable 中排序:true
- alfresco - 可以将 Alfresco 用作 JCR 实现吗?
- oracle - 执行 IMP 命令时的 IMP-00403
- python - list(dictionary.values()) 与 dictionary.values()
- profiling - VisualVM 是否在检测字节码?