
本文介绍一种简洁高效的方法,使用字典聚合(setdefault)将具有相同 id、table 和 category 的字典归并为嵌套结构,外层保留公共字段,内层以 'products' 键聚合所有商品明细。
本文介绍一种简洁高效的方法,使用字典聚合(`setdefault`)将具有相同 `id`、`table` 和 `category` 的字典归并为嵌套结构,外层保留公共字段,内层以 `'products'` 键聚合所有商品明细。
在数据处理中,常需将扁平化的字典列表按多个字段分组,并重构为层级化结构——例如将订单明细按订单 ID 和品类聚合为“主-子”嵌套格式。相比 itertools.groupby(要求输入已排序且逻辑较重),基于 dict.setdefault() 的原生字典聚合更直观、鲁棒且无需预排序。
核心思路是:
- 以 (id, table, category) 元组作为复合键,确保语义唯一性;
- 利用 setdefault(key, []) 自动初始化空列表并追加子项;
- 最后将聚合字典解构为标准列表,每个元素包含原始公共字段 + 新增的 'products' 列表。
以下是完整实现代码:
list_dict = [
{'id': 1, 'table': 8, 'category': 'fruit', 'product': 'banana', 'price': 4, 'qty': 5},
{'id': 1, 'table': 8, 'category': 'fruit', 'product': 'apple', 'price': 5, 'qty': 9},
{'id': 1, 'table': 8, 'category': 'fruit', 'product': 'orange', 'price': 6, 'qty': 3},
{'id': 2, 'table': 5, 'category': 'vegetable', 'product': 'carrot', 'price': 4, 'qty': 5},
{'id': 2, 'table': 5, 'category': 'vegetable', 'product': 'potato', 'price': 2, 'qty': 3}
]
# 步骤1:按 (id, table, category) 聚合 product 子项
grouped = {}
for item in list_dict:
key = (item['id'], item['table'], item['category'])
grouped.setdefault(key, []).append({
'product': item['product'],
'price': item['price'],
'qty': item['qty']
})
# 步骤2:重构为最终嵌套列表
result = [
{
'id': k[0],
'table': k[1],
'category': k[2],
'products': products
}
for k, products in grouped.items()
]
print(result)✅ 优势说明:
- 无需排序:groupby 要求输入严格按分组键有序,而本方法对任意顺序输入均可靠;
- 可读性强:逻辑直白,易于调试与扩展(如增加更多聚合键或子字段);
- 性能良好:单次遍历 O(n) 时间复杂度,空间开销可控。
⚠️ 注意事项:
- 若原始数据中存在 None 或不可哈希值(如列表、字典)作为分组字段,需先做类型转换或清洗;
- 如需保持原始顺序(如按首次出现的 id 排序),可在最后对 result 按 key[0] 排序:sorted(result, key=lambda x: x['id']);
- 扩展场景(如同时聚合多个子字段)只需调整 append() 中的字典结构即可。
该方法是 Python 数据聚合的经典实践,兼顾简洁性与工程实用性,适用于 API 响应组装、报表生成及 ETL 预处理等典型场景。

















