python - 根据条件合并两个字典列表
问题描述
我有两个字典列表,我需要在任何时候合并它们USA
并且GOOG
它们是相同的。
list1 =
[{'USA': 'Eastern',
'GOOG': '2019',
'Up': {'Upfront': 45},
'Right': {'Upfront': 12}},
{'USA': 'Western',
'GOOG': '2019',
'Up': {'Upfront': 10},
'Right': {'Upfront': 15}}]
list2=
[{'USA': 'Western',
'GOOG': '2019',
'Down': {'Downback': 35},
'Right': {'Downback': 25}},
{'USA': 'Eastern',
'GOOG': '2018',
'Down': {'Downback': 15},
'Right': {'Downback': 55}}]
因为USA
和GOOG
中的第二个元素具有相同的值list1
中的第二个元素和list2
,因此它们应该被合并。预期的结果如下 -
Result =
[{'USA': 'Eastern',
'GOOG': '2019',
'Up': {'Upfront': 45},
'Right': {'Upfront': 12}},
{'USA': 'Western',
'GOOG': '2019',
'Up': {'Upfront': 10},
'Down': {'Downback': 35},
'Right': {'Upfront': 15, 'Downback': 25}},
{'USA': 'Eastern',
'GOOG': '2018',
'Down': {'Downback': 15},
'Right': {'Downback': 55}}]
我们如何为此编写通用代码。我尝试使用defaultdict,但不知道如何连接任意数量的其余字典。
我的尝试:
from collections import defaultdict
dics = list1+list2
for dic in dics:
for key, val in dic.items():
dd[key].append(val)
for dic in dics:
for key, val in dic.items():
dd[key].append(val)
解决方案
您需要两个算法任务:找到 USA 和 GOOGL 具有相同值的记录,然后加入然后以如果两个记录中存在相同的键,则合并它们的值的方式执行此操作。
第一种天真的方法是有一个 for 循环来迭代 list1 的值,并且对于每个值,迭代 list2 的所有值 - 两个单独的循环不会削减它,你需要两个嵌套 for
循环:
for element in list1:
for other_element in list2:
if ...:
...
虽然这种方法可行,并且适用于小型列表(例如,<1000 条记录),但它需要的时间和资源与列表大小的平方成正比 - 也就是说,对于接近 ~ 的列表我们所说的 1000 个项目 100 万次迭代。如果列表本身是 1.000.000 项,则计算将进行 1 * 10^12 次比较,这在当今的计算机中根本不可行。
因此,一个不错的解决方案是以比较键用作哈希的方式重新创建一个列表 - 这是通过将列表复制到字典中的键是您要比较的值,然后只在第二个列表上迭代一次。由于字典有固定的时间来查找项目,这将使比较次数与您的列表大小成正比。
您任务的第二部分是比较将一条记录复制到结果列表,并更新结果副本上的键,以便合并任何重复的键。为了避免在复制第一条记录时出现问题,我们使用 Python 更安全copy.deepcopy
,这将确保子字典与原始记录中的对象不同,并且将保持隔离。
from copy import deepcopy
def merge_lists(list1, list2):
# create dictionary from list1:
dict1 = {(record["GOOG"], record["USA"]): record for record in list1}
#compare elements in list2 to those on list1:
result = {}
for record in list2:
ckey = record["GOOG"], record["USA"]
new_record = deepcopy(record)
if ckey in dict1:
for key, value in dict1[ckey].items():
if key in ("GOOG", "USA"):
# Do not merge these keys
continue
# Dict's "setdefault" finds a key/value, and if it is missing
# creates a new one with the second parameter as value
new_record.setdefault(key, {}).update(value)
result[ckey] = new_record
# Add values from list1 that were not matched in list2:
for key, value in dict1.items():
if key not in result:
result[key] = deepcopy(value)
return list(result.values())
推荐阅读
- java - 列表
另一个列表的子集 忽略大小写? - selenium - 我正在尝试找出将从以下 HTML 中检索 img alt 文本的 XPath
- java - 如何在java中更新控制台输出?
- java - 未使用 Spring CommonsRequestLoggingFilter 记录响应内容
- javascript - javascript中的原型阴影和原型链接有什么区别
- java - 如何建立与数据库的连接?对于获取我文件的人
- javascript - plotly.js 瀑布图,上下不同颜色
- excel - Excel ADDRESS 和 COUNTIF 函数
- java - 方法 onComplete 不起作用
- c - 如何从linux用户空间标记一些文件以便在内核空间对它们应用一些操作