Python两字典列表按id与环境匹配累加成本的实现问题
问题根因
原代码有三个核心bug导致结果不符合预期:
- 参数传反:
main函数定义第一个参数是formatted_results_ecs、第二个是formatted_list,但调用时写的是main(formatted_list, formatted_results_ecs),两个列表从传入开始就错位,匹配逻辑从根上失效 - 累加逻辑错误:嵌套双层循环的写法下,同一个id+环境在ecs列表里有多条记录时,每次匹配到都会把当前ecs成本叠加在已经累加过的cost值上,导致重复计算;且
ecs_deduction统计的是累加后的总成本,不是ecs部分的抵扣额,统计值不准 - 无去重逻辑:没有提前校验
formatted_list本身的重复条目,如果初始列表存在同id同环境的多条记录,会出现多次累加、结果重复的问题
以你提到的idff66d353-6644-4c61-9c22-204960d65a18为例,它在ecs列表里有2条prod、2条nonprod记录,原嵌套循环每扫到一条ecs记录就遍历整个formatted_list,很容易出现重复累加、条目重复的问题。
实现逻辑
整体方案分三步,时间复杂度从原嵌套循环的O(n*m)降到O(n+m),同时从机制上保证无重复条目:
- 预处理
formatted_list,以(id, environment)作为唯一键构建查找字典,同键的条目先合并cost,保证每个键只对应唯一条目,从根源消除重复 - 遍历
formatted_results_ecs,按相同的(id, environment)键匹配查找字典中的条目,把ecs的cost累加到对应项,同时只统计ecs部分的总抵扣额,避免重复计算 - 把处理完的字典值转回列表,最终结果里每个id只会保留prod、nonprod两个环境的唯一条目,不会出现同id同环境的重复记录。
修正后的代码
def main(formatted_results_ecs, formatted_list): ecs_deduction = 0 # 第一步:构建去重的成本映射,解决原列表可能存在的重复条目问题 cost_map = {} for item in formatted_list: key = (item["id"], item["environment"]) if key not in cost_map: # 存副本避免修改原列表的引用关联 cost_map[key] = item.copy() else: # 原列表存在同键重复项时先合并成本 cost_map[key]["cost"] += item["cost"] # 第二步:遍历ecs列表累加对应成本 for ecs_item in formatted_results_ecs: key = (ecs_item["id"], ecs_item["environment"]) if key in cost_map: cost_map[key]["cost"] += ecs_item["cost"] ecs_deduction += ecs_item["cost"] # 转回列表结构输出 final_formatted_list = list(cost_map.values()) return final_formatted_list, ecs_deduction if __name__ == '__main__': formatted_results_ecs = [ {'id': 'ffd07d03-e10b-4d60-8e28-e4ab617bf394', 'cost': 3.2980019999999994, 'environment': 'prod'}, {'id': 'ffc87314-16e4-4c77-b5ec-f34066458ce4', 'cost': 215.82577600000002, 'environment': 'prod'}, {'id': 'ff66d353-6644-4c61-9c22-204960d65a18', 'cost': 291.61807799999997, 'environment': 'prod'}, {'id': 'a855d85f-65e4-40bb-a21f-6ceea77628cc', 'cost': 19.041902000000004, 'environment': 'prod'}, {'id': 'aa385029-afa6-4f1a-a1d9-d88b7d934699', 'cost': 2.033628000000001, 'environment': 'prod'}, {'id': 'adf44794-50eb-45db-9323-6ce5fd31699e', 'cost': 1120.8391390000004, 'environment': 'prod'}, {'id': 'b13a0676-6926-49db-808c-3c968a9278eb', 'cost': 15145.140081999996, 'environment': 'prod'}, {'id': 'e4c3c7b9-5941-4cf7-aa90-f63a142ccaf4', 'cost': 3319.4728399999995, 'environment': 'prod'}, {'id': 'ff66d353-6644-4c61-9c22-204960d65a18', 'cost': 6.0234558329471, 'environment': 'nonprod'}, {'id': 'ff66d353-6644-4c61-9c22-204960d65a18', 'cost': 7.9407999472248, 'environment': 'prod'}, {'id': '2d1e7f15-d3bb-4649-996e-a7afb55b7637', 'cost': 5.940205, 'environment': 'prod'}, {'id': '6841509d-1d68-4af3-b04e-8bc7e87d0c89', 'cost': 651.016164, 'environment': 'prod'}, {'id': 'ffd07d03-e10b-4d60-8e28-e4ab617bf394', 'cost': 3.287444999999999, 'environment': 'nonprod'}, {'id': 'ffc87314-16e4-4c77-b5ec-f34066458ce4', 'cost': 214.46528800000002, 'environment': 'nonprod'}, {'id': 'ff66d353-6644-4c61-9c22-204960d65a18', 'cost': 291.55481199999997, 'environment': 'nonprod'}, {'id': 'aa385029-afa6-4f1a-a1d9-d88b7d934699', 'cost': 2.0193450000000013, 'environment': 'nonprod'}, ] formatted_list = [ {'id': 'ffd07d03-e10b-4d60-8e28-e4ab617bf394', 'cost': 13.431203414269257, 'environment': 'nonprod'}, {'id': 'ffc87314-16e4-4c77-b5ec-f34066458ce4', 'cost': 3.1723085934801296, 'environment': 'nonprod'}, {'id': 'ff66d353-6644-4c61-9c22-204960d65a18', 'cost': 602.0234558329471, 'environment': 'nonprod'}, {'id': 'ff66d353-6644-4c61-9c22-204960d65a18', 'cost': 607.9407999472248, 'environment': 'prod'}, {'id': 'ff4f589f-2616-4f5e-9fb0-09e7ab3d200c', 'cost': 0.187242731922548, 'environment': 'prod'}, {'id': 'ff2041fb-711f-4bca-a336-5c6ac07fb8f3', 'cost': 1.179409983e-06, 'environment': 'nonprod'}, {'id': 'ff2041fb-711f-4bca-a336-5c6ac07fb8f3', 'cost': 1.179409983e-06, 'environment': 'prod'}, {'id': 'fba58f4f-303c-4a20-86d3-294714c8db5c', 'cost': 14.494946621907866, 'environment': 'nonprod'}, {'id': 'f8780ef9-0211-486b-ac2d-1b85d6bcb9da', 'cost': 19.592325435434688, 'environment': 'nonprod'}, {'id': 'f8780ef9-0211-486b-ac2d-1b85d6bcb9da', 'cost': 19.288246392238705, 'environment': 'prod'}, {'id': 'f7f16766-1212-4747-9c98-7a37d125e850', 'cost': 0.8798593169569822, 'environment': 'nonprod'}, {'id': 'f7d59e13-cba1-4a13-af57-8c4aec3ee281', 'cost': 30.22516723291206, 'environment': 'prod'}, {'id': 'f7d59e13-cba1-4a13-af57-8c4aec3ee281', 'cost': 29.88632221088805, 'environment': 'nonprod'}, {'id': 'f742f6ea-01dc-4add-a283-6afa6656a87b', 'cost': 18.657917564221908, 'environment': 'prod'} ] # 修正参数顺序,第一个传ecs成本列表,第二个传原始待合并列表 final_list, total_ecs_deduction = main(formatted_results_ecs, formatted_list) # 打印示例id的结果验证 for item in final_list: if item["id"] == "ff66d353-6644-4c61-9c22-204960d65a18": print(item)
结果验证
针对示例idff66d353-6644-4c61-9c22-204960d65a18,计算结果完全准确:
- prod环境:原列表成本607.9408 + ecs两条prod记录成本(291.6181 + 7.9408) = 907.4997
- nonprod环境:原列表成本602.0235 + ecs两条nonprod记录成本(6.0235 + 291.5548) = 899.6017
最终该id仅保留prod、nonprod两条唯一记录,无重复项,成本累加正确。
内容的提问来源于stack exchange,提问作者poppinpython
相关产品推荐
相关产品推荐

