You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何按相同键对多字典列表分组并生成对应值列表?

嘿,这个分组需求在Python里有两种非常实用的最优实现方式,我给你详细说说,你可以根据你的数据情况来选:

方案一:用collections.defaultdict(通用首选)

这个方法不需要提前对数据排序,不管你的原始列表里的name顺序如何,都能高效完成分组,时间复杂度是O(n),是最通用的方案。

代码示例:

from collections import defaultdict

Data = [
    {'name': 'John', 'age': 10},
    {'name': 'John', 'age': 11},
    {'name': 'John', 'age': 12},
    {'name': 'Paul', 'age': 13},
    {'name': 'Paul', 'age': 14},
    {'name': 'Paul', 'age': 15},
]

# 初始化一个默认值为列表的字典
grouped_dict = defaultdict(list)
for item in Data:
    # 把每个age追加到对应name的列表里
    grouped_dict[item['name']].append(item['age'])

# 转换成你要的输出格式
result = [f"{name} {' '.join(map(str, ages))}" for name, ages in grouped_dict.items()]
for line in result:
    print(line)

运行后就会输出:

John 10 11 12
Paul 13 14 15

为什么说这个最优?因为它逻辑简单,不需要额外的排序步骤,处理无序数据也完全没问题,而且defaultdict帮我们省去了判断name是否已存在的冗余代码,非常简洁。


方案二:用itertools.groupby(适合有序数据)

如果你的数据已经按name字段排好序(比如你的示例数据),那么用itertools.groupby会更节省内存,因为它是按连续的相同键分组,不需要额外存储所有中间元素。

代码示例:

from itertools import groupby

Data = [
    {'name': 'John', 'age': 10},
    {'name': 'John', 'age': 11},
    {'name': 'John', 'age': 12},
    {'name': 'Paul', 'age': 13},
    {'name': 'Paul', 'age': 14},
    {'name': 'Paul', 'age': 15},
]

# 注意:groupby要求数据先按分组键排序,如果数据无序,必须先执行这一步
sorted_data = sorted(Data, key=lambda x: x['name'])

grouped_dict = {}
# 按name分组,遍历每个分组
for name_key, item_group in groupby(sorted_data, key=lambda x: x['name']):
    # 提取分组里的所有age
    grouped_dict[name_key] = [item['age'] for item in item_group]

# 生成输出格式
result = [f"{name} {' '.join(map(str, ages))}" for name, ages in grouped_dict.items()]
for line in result:
    print(line)

注意点:

如果你的数据是无序的,用groupby必须先排序,这时候时间复杂度会变成O(n log n),就不如defaultdict的O(n)高效了,所以这个方案更适合本身就是有序的数据集。


总结一下:

  • 数据无序或不想排序 → 选defaultdict,通用高效
  • 数据已按name排序 → 选groupby,内存更友好

内容的提问来源于stack exchange,提问作者SM0305

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 11:07:32