Python字典列表按键分组聚合的向量化高效实现方案咨询
列表按字段分组聚合的实现方案
任务规则
- 输入:字典列表,单条字典固定包含
class、studentid两个键 - 输出:字典结构,键为
class字段的去重后取值,值为该班级下所有studentid组成的列表
Python 场景方案
1. 原生循环方案(小数据量最优)
你当前使用的collections.defaultdict实现是纯Python场景下的通用最优解,没有第三方依赖、逻辑直白,数据量在1万条以内时性能优于绝大多数花活写法,代码如下:
from collections import defaultdict students = [ {'class': 1, 'studentid': 1}, {'class': 1, 'studentid': 2}, {'class': 2, 'studentid': 3}, {'class': 2, 'studentid': 4}, {'class': 3, 'studentid': 5} ] classes = defaultdict(list) for student in students: classes[student['class']].append(student['studentid']) # 输出:{1: [1, 2], 2: [3, 4], 3: [5]}
如果不想导入defaultdict,也可以用普通字典的setdefault方法实现,性能差距极小:
classes = {} for student in students: classes.setdefault(student['class'], []).append(student['studentid'])
2. 向量化方案(大数据量场景)
当数据量达到10万条以上时,可以用pandas的向量化分组逻辑提速,底层分组逻辑由C实现,比纯Python层循环快5~20倍。
注意:数据量小于1万条时不要用pandas方案,DataFrame初始化的固定开销会让整体速度比原生defaultdict慢2~3倍。
import pandas as pd df = pd.DataFrame(students) classes = df.groupby('class')['studentid'].agg(list).to_dict()
3. 标准库itertools方案(预排序数据适用)
如果输入列表已经提前按class字段排好序,可以用itertools.groupby减少哈希表判断开销,未排序的数据用这个方法需要先排序,整体性能反而不如defaultdict方案:
from itertools import groupby from operator import itemgetter # 仅当students已按class排序时可跳过sorted步骤 students_sorted = sorted(students, key=itemgetter('class')) classes = { cls: [stu['studentid'] for stu in group] for cls, group in groupby(students_sorted, key=itemgetter('class')) }
其他技术栈通用实现
JavaScript/TypeScript
用数组reduce方法即可实现,无额外依赖:
const students = [ {class: 1, studentid: 1}, {class: 1, studentid: 2}, {class: 2, studentid: 3}, {class: 2, studentid: 4}, {class: 3, studentid: 5} ] const classes = students.reduce((res, cur) => { res[cur.class] ??= [] res[cur.class].push(cur.studentid) return res }, {})
Go
原生map+循环即可,性能极高,适合后端服务场景:
package main type Student struct { Class int StudentId int } func main() { students := []Student{ {Class: 1, StudentId: 1}, {Class: 1, StudentId: 2}, {Class: 2, StudentId: 3}, {Class: 2, StudentId: 4}, {Class: 3, StudentId: 5}, } classMap := make(map[int][]int) for _, stu := range students { classMap[stu.Class] = append(classMap[stu.Class], stu.StudentId) } }
SQL
如果数据存储在数据库中,直接用数据库内置聚合函数处理是性能最高的方案,不需要把全量数据拉到应用内存计算:
SELECT class, JSON_ARRAYAGG(studentid) AS student_ids FROM students GROUP BY class
内容的提问来源于stack exchange,提问作者Treeboy
相关产品推荐
相关产品推荐

