案例: 合并表格使用 Dict¶
(date: 2025-11-18)
学习建议:建议先完成 dict-tutorial-1.md 的基础学习,再学习本案例。
提出问题,需求分析,技术方案,掌握工具,实践验证——五大环节,完成一个案例。
学习目标:
理解列表和字典在数据处理中的不同应用场景
掌握将列表数据转换为字典的方法
学会使用字典进行高效的数据合并操作
理解不同数据结构的性能特点
问题与分析¶
原数据¶
# 语文老师提供
chinese_scores = [["张三", "S001", 85], ["李四", "S002", 92], ["王五", "S003", 78]]
# 数学老师提供
math_scores = [["张三", "S001", 90], ["李四", "S002", 87], ["王五", "S003", 85]]
# 英语老师提供
english_scores = [["S001", "张三", 88], ["S002", "李四", 85], ["S003", "王五", 80]]
期望的结果¶
期望得到一个合并后的成绩表,包含每个学生的所有科目成绩:
[
["学号", "姓名", "语文", "数学", "英语"],
["S001", "张三", 85, 90, 88],
["S002", "李四", 92, 87, 85],
["S003", "王五", 78, 85, 80]
]
整合数据¶
输入为整齐的三个数据表(准备)¶
chinese = [
['S001', '张三', 85],
['S002', '李四', 92],
['S003', '王五', 78]
]
math = [
['S001', '张三', 90],
['S002', '李四', 87],
['S003', '王五', 85]
]
english = [
['S001', '张三', 88],
['S002', '李四', 85],
['S003', '王五', 80]
]
合并成 dict 总表¶
期望:
{
S001: {'姓名': '张三', '语文': 85, '数学': 90, '英语': 88}
S002: {'姓名': '李四', '语文': 92, '数学': 87, '英语': 85}
S003: {'姓名': '王五', '语文': 78, '数学': 85, '英语': 80}
}
先处理语文¶
# 创建空字典来存储合并后的数据
student_scores = {}
# 处理语文成绩
for record in chinese:
student_id, name, score = record
student_scores[student_id] = {
'姓名': name,
'语文': score
}
for student_id, scores in student_scores.items():
print(f"{student_id}: {scores}")
接着处理数学¶
# 处理数学成绩
for record in math:
student_id, name, score = record
# 如果该学生已存在,只更新数学成绩;如果不存在,创建新记录
if student_id in student_scores:
student_scores[student_id]['数学'] = ...
else:
student_scores[student_id] = {
'姓名': name,
'数学': ...
}
for student_id, scores in student_scores.items():
print(f"{student_id}: {scores}")
再接着处理英语成绩¶
# 处理英语成绩
for record in english:
student_id, name, score = record
if student_id in student_scores:
student_scores[student_id]['英语'] = score
else:
student_scores[student_id] = {
'姓名': name,
...: ...
}
# 打印合并后的结果
print("合并后的学生成绩表:")
for student_id, scores in student_scores.items():
print(f"{student_id}: {scores}")
打印结果¶
合并后的学生成绩表:
S001: {'姓名': '张三', '语文': 85, '数学': 90, '英语': 88}
S002: {'姓名': '李四', '语文': 92, '数学': 87, '英语': 85}
S003: {'姓名': '王五', '语文': 78, '数学': 85, '英语': 80}
有两个主要问题:
[homework] 处理3们不同学科时,代码是相同的,如何合并?
最后的结果和要求有所不同,如何改进?
字典转列表¶
你说得非常对!这部分跨度确实太大了。直接从"先处理语文→再处理数学"的渐进式教学,突然跳到了一个复杂的、用列表存储的字典方案,逻辑转换太突兀。
让我重新设计这个过渡:
改进方案:渐进式教学¶
阶段1:先用字典完成数据合并(已完成)¶
# 这是我们前面已经完成的字典结构
student_scores = {
'S001': {'姓名': '张三', '语文': 85, '数学': 90, '英语': 88},
'S002': {'姓名': '李四', '语文': 92, '数学': 87, '英语': 85},
'S003': {'姓名': '王五', '语文': 78, '数学': 85, '英语': 80}
}
阶段2:分析字典的局限性,引出列表需求¶
讨论问题:
字典虽然查询方便,但最终我们需要表格形式的结果
很多场景下(如导出CSV、显示表格)需要列表结构
如何把字典转换成期望的列表格式?
阶段3:手动转换示范¶
# 方法1:手动构建(理解逻辑)
header = ["学号", "姓名", "语文", "数学", "英语"]
result = [header] # 先放表头
# 手动添加第一条数据
result.append(["S001", "张三", 85, 90, 88])
result.append(["S002", "李四", 92, 87, 85])
result.append(["S003", "王五", 78, 85, 80])
print("手动构建的结果:")
for row in result:
print(row)
阶段4:从字典自动转换¶
# 方法2:从字典自动转换
result_auto = [header]
for student_id, scores in student_scores.items():
row = [
student_id,
scores['姓名'],
scores['语文'],
scores['数学'],
scores['英语']
]
result_auto.append(row)
print("自动转换的结果:")
for row in result_auto:
print(row)
阶段5:介绍"列表存储"方案¶
引出思路:"其实,我们也可以从一开始就用列表来存储,避免最后的转换..."
# 方法3:从一开始就用列表存储(你原来那部分的简化版)
student_dict_list = {}
# 先只处理一个科目来演示
for record in chinese:
student_id, name, score = record
student_dict_list[student_id] = [student_id, name, score, 0, 0] # 数学英语先填0
print("处理语文后的中间结果:")
for student_id, row in student_dict_list.items():
print(f"{student_id}: {row}")
阶段6:逐步完善多科目处理¶
# 接着处理数学
for record in math:
student_id, name, score = record
if student_id in student_dict_list:
student_dict_list[student_id][3] = score # 更新数学成绩
else:
student_dict_list[student_id] = [student_id, name, 0, score, 0]
print("处理数学后的结果:")
for student_id, row in student_dict_list.items():
print(f"{student_id}: {row}")
# 最后处理英语(让学生自己尝试)
阶段7:最终优化成完整方案¶
# 完整的优化方案(现在学生已经理解每一步了)
student_dict_final = {}
subjects = [chinese, math, english]
for subject_data in subjects:
for record in subject_data:
student_id, name, score = record
if student_id not in student_dict_final:
student_dict_final[student_id] = [student_id, name, 0, 0, 0]
if subject_data == chinese:
student_dict_final[student_id][2] = score
elif subject_data == math:
student_dict_final[student_id][3] = score
elif subject_data == english:
student_dict_final[student_id][4] = score
# 最终转换
final_result = [header] + list(student_dict_final.values())
这样的分解是不是更符合学习逻辑?从"为什么需要转换" → "如何手动转换" → "如何自动转换" → "如何从一开始就用目标格式",让学生理解每种方案的思考过程。
封装:直接合并成列表¶
# 创建字典来存储学生信息
student_dict = {}
# 处理所有科目数据
subjects = [chinese, math, english]
for subject_data in subjects:
for record in subject_data:
student_id, name, score = record
if student_id not in student_dict:
# 初始化学生信息:学号,姓名,语文,数学,英语
student_dict[student_id] = [student_id, name, 0, 0, 0]
# 根据当前科目确定成绩位置
if subject_data == chinese:
student_dict[student_id][2] = score # 语文成绩
elif subject_data == math:
student_dict[student_id][3] = score # 数学成绩
elif subject_data == english:
student_dict[student_id][4] = score # 英语成绩
# 转换为最终的列表格式
merged_list = list(student_dict.values())
# 打印结果
print("合并后的学生成绩表:")
print("学号\t姓名\t语文\t数学\t英语")
for student in merged_list:
print(f"{student[0]}\t{student[1]}\t{student[2]}\t{student[3]}\t{student[4]}")
Dict 与 List 比较¶
使用字典可以更优雅地解决这个问题。字典的优势在于:
快速查找:通过键直接访问,时间复杂度 O(1)
灵活性:不需要关心数据顺序
容错性:可以处理缺失数据
可读性:键名具有语义信息