如何基于student_id对含嵌套字典列表的字典列表分组聚合?
按学生ID聚合历年成绩数据
问题描述
我有如下格式的字典列表:
d = [ {'value': [{'student_id': 45522, 'marks': 75}, {'student_id': 70515, 'marks': 80}],'year':2001}, {'value': [{'student_id': 45522, 'marks': 35}, {'student_id': 70515, 'marks': 90}],'year':2002}, {'value': [{'student_id': 45522, 'marks': 60}, {'student_id': 70515, 'marks': 89}],'year':2003} ]
希望将数据按学生ID聚合,得到每个学生的历年年份和对应成绩的列表:
student_marks_data = [ {"student_id":45522, "years":[2001,2002,2003], "marks":[75,35,60]}, {"student_id":70515, "years":[2001,2002,2003], "marks":[80,90,89]} ]
注:你提供的期望结果中45522的marks字段有个30,应该是笔误,这里按原始数据的35处理。
我了解过itertools库,但不清楚如何用它实现这个需求。
解决方案
方法1:用普通字典直接聚合(直观高效)
这种方法不需要额外库,直接遍历原始数据,逐步收集每个学生的年份和成绩:
d = [ {'value': [{'student_id': 45522, 'marks': 75}, {'student_id': 70515, 'marks': 80}],'year':2001}, {'value': [{'student_id': 45522, 'marks': 35}, {'student_id': 70515, 'marks': 90}],'year':2002}, {'value': [{'student_id': 45522, 'marks': 60}, {'student_id': 70515, 'marks': 89}],'year':2003} ] # 用字典存储每个学生的信息,key为student_id student_dict = {} for entry in d: current_year = entry['year'] for student_info in entry['value']: sid = student_info['student_id'] current_marks = student_info['marks'] if sid not in student_dict: # 首次遇到该学生,初始化数据结构 student_dict[sid] = { 'student_id': sid, 'years': [], 'marks': [] } # 追加当前年份和成绩 student_dict[sid]['years'].append(current_year) student_dict[sid]['marks'].append(current_marks) # 把字典的值转为列表,就是最终结果 student_marks_data = list(student_dict.values()) print(student_marks_data)
方法2:用itertools.groupby实现
如果一定要用itertools.groupby,需要先将数据展开并排序(因为groupby仅对连续相同键的元素分组):
from itertools import groupby d = [ {'value': [{'student_id': 45522, 'marks': 75}, {'student_id': 70515, 'marks': 80}],'year':2001}, {'value': [{'student_id': 45522, 'marks': 35}, {'student_id': 70515, 'marks': 90}],'year':2002}, {'value': [{'student_id': 45522, 'marks': 60}, {'student_id': 70515, 'marks': 89}],'year':2003} ] # 步骤1:展开所有学生记录,给每条记录添加year字段 flattened_records = [] for entry in d: year = entry['year'] for student in entry['value']: flattened_records.append({ 'student_id': student['student_id'], 'year': year, 'marks': student['marks'] }) # 步骤2:按student_id排序,确保相同ID的记录连续 sorted_records = sorted(flattened_records, key=lambda x: x['student_id']) # 步骤3:分组并聚合年份和成绩 student_marks_data = [] for student_id, group in groupby(sorted_records, key=lambda x: x['student_id']): years = [] marks = [] for item in group: years.append(item['year']) marks.append(item['marks']) student_marks_data.append({ 'student_id': student_id, 'years': years, 'marks': marks }) print(student_marks_data)
两种方法都能得到目标结果,第一种更直接高效,第二种适合需要使用itertools的场景。
内容的提问来源于stack exchange,提问作者kishanparmar
相关产品推荐
相关产品推荐

