跳到主要内容

练习:数据处理脚本 📊

目标

假设你是一个班级的助教,手上有一份学生成绩数据。你的任务是写一个脚本来:

  1. 解析数据 — 把原始文本变成可操作的数据结构
  2. 计算统计信息 — 平均分、最高分、最低分
  3. 找出优等生和需要关注的学生
  4. 生成一份文字报告

这个练习的核心是数组/列表操作和对象/字典操作 —— 你在前面几个模块学到的东西,现在要全部串起来用了。

样本数据

我们用一个简单的"CSV 风格"字符串来模拟数据(实际开发中你可能从文件读取,但原理一样):

加载代码编辑器中……

任务分解

别试图一口气写完!我们把大任务拆成小步骤。

第一步:解析数据

把上面的原始字符串变成一个结构化的列表/数组。每个学生应该是一个字典/对象,大概长这样:

{ name: "张三", chinese: 85, math: 92, english: 78 }
加载代码编辑器中……
💡 第一步提示

Python:

  • raw.strip().split("\n") 把文本按行拆开
  • line.split(",") 把每行按逗号拆开
  • int("85") 把字符串转数字
  • 列表推导式写起来很优雅:[{"name": parts[0], ...} for parts in ...]

JavaScript:

  • raw.trim().split("\n") 同理
  • line.split(",") 同理
  • Number("85")parseInt("85") 转数字
  • .map() 就是 JS 版的列表推导式

第二步:计算每个学生的平均分

给每个学生对象加一个 average 字段。

加载代码编辑器中……

第三步:找出最高分和最低分

写两个函数,分别找出平均分最高和最低的学生。

加载代码编辑器中……

第四步:生成报告

把前面所有结果组合起来,输出一份像样的文字报告:

========== 班级成绩报告 ==========
学生人数: 8
全班平均分: 82.1

🏆 最高分: 赵六(95.0分)
⚠️ 最低分: 钱七(57.7分)

--- 各科平均 ---
语文: 82.5
数学: 81.4
英语: 83.3

--- 优秀学生(平均分≥90)---
赵六: 95.0
李四: 91.0

--- 需关注学生(平均分<60)---
钱七: 57.7
==================================

这一步主要考验你的字符串格式化筛选/过滤能力。

完整参考答案

🔑 点击展开 Python 完整答案
raw_data = """张三,85,92,78
李四,90,88,95
王五,72,65,80
赵六,95,98,92
钱七,60,55,58
孙八,88,76,90
周九,78,82,85
吴十,92,95,88"""

def parse_data(raw):
students = []
for line in raw.strip().split("\n"):
parts = line.split(",")
students.append({
"name": parts[0],
"chinese": int(parts[1]),
"math": int(parts[2]),
"english": int(parts[3]),
})
return students

def add_averages(students):
for s in students:
avg = (s["chinese"] + s["math"] + s["english"]) / 3
s["average"] = round(avg, 1)

def subject_average(students, subject):
total = sum(s[subject] for s in students)
return round(total / len(students), 1)

def generate_report(students):
add_averages(students)

all_avg = round(
sum(s["average"] for s in students) / len(students), 1
)
top = max(students, key=lambda s: s["average"])
bottom = min(students, key=lambda s: s["average"])

excellent = [s for s in students if s["average"] >= 90]
at_risk = [s for s in students if s["average"] < 60]

print("=" * 35)
print(" 班级成绩报告")
print("=" * 35)
print(f"学生人数: {len(students)}")
print(f"全班平均分: {all_avg}")
print()
print(f"最高分: {top['name']}{top['average']}分)")
print(f"最低分: {bottom['name']}{bottom['average']}分)")
print()
print("--- 各科平均 ---")
print(f"语文: {subject_average(students, 'chinese')}")
print(f"数学: {subject_average(students, 'math')}")
print(f"英语: {subject_average(students, 'english')}")
print()
print("--- 优秀学生(平均分>=90)---")
for s in excellent:
print(f" {s['name']}: {s['average']}")
if not excellent:
print(" (无)")
print()
print("--- 需关注学生(平均分<60)---")
for s in at_risk:
print(f" {s['name']}: {s['average']}")
if not at_risk:
print(" (无)")
print("=" * 35)

students = parse_data(raw_data)
generate_report(students)
🔑 点击展开 JavaScript 完整答案
const rawData = `张三,85,92,78
李四,90,88,95
王五,72,65,80
赵六,95,98,92
钱七,60,55,58
孙八,88,76,90
周九,78,82,85
吴十,92,95,88`

function parseData(raw) {
return raw.trim().split("\n").map((line) => {
const parts = line.split(",")
return {
name: parts[0],
chinese: Number(parts[1]),
math: Number(parts[2]),
english: Number(parts[3]),
}
})
}

function addAverages(students) {
for (const s of students) {
const avg = (s.chinese + s.math + s.english) / 3
s.average = Math.round(avg * 10) / 10
}
}

function subjectAverage(students, subject) {
const total = students.reduce((sum, s) => sum + s[subject], 0)
return Math.round((total / students.length) * 10) / 10
}

function generateReport(students) {
addAverages(students)

const allAvg = Math.round(
(students.reduce((sum, s) => sum + s.average, 0) / students.length) * 10
) / 10

const top = students.reduce((best, s) =>
s.average > best.average ? s : best
)
const bottom = students.reduce((worst, s) =>
s.average < worst.average ? s : worst
)

const excellent = students.filter((s) => s.average >= 90)
const atRisk = students.filter((s) => s.average < 60)

console.log("=".repeat(35))
console.log(" 班级成绩报告")
console.log("=".repeat(35))
console.log(`学生人数: ${students.length}`)
console.log(`全班平均分: ${allAvg}`)
console.log()
console.log(`最高分: ${top.name}${top.average}分)`)
console.log(`最低分: ${bottom.name}${bottom.average}分)`)
console.log()
console.log("--- 各科平均 ---")
console.log(`语文: ${subjectAverage(students, "chinese")}`)
console.log(`数学: ${subjectAverage(students, "math")}`)
console.log(`英语: ${subjectAverage(students, "english")}`)
console.log()
console.log("--- 优秀学生(平均分>=90)---")
if (excellent.length > 0) {
for (const s of excellent) {
console.log(` ${s.name}: ${s.average}`)
}
} else {
console.log(" (无)")
}
console.log()
console.log("--- 需关注学生(平均分<60)---")
if (atRisk.length > 0) {
for (const s of atRisk) {
console.log(` ${s.name}: ${s.average}`)
}
} else {
console.log(" (无)")
}
console.log("=".repeat(35))
}

const students = parseData(rawData)
generateReport(students)
🏋️AI 练习

完成基础版本之后,试试这些扩展:

  1. 排序输出 — 按平均分从高到低排列所有学生
  2. 等级划分 — A(90+)、B(80-89)、C(70-79)、D(60-69)、F(<60),统计每个等级的人数
  3. 单科冠军 — 找出每一科的最高分是谁
  4. 及格率 — 计算每科的及格率(>=60 的比例)
问问 AI

把你的代码贴给 AI,问它:"这段数据处理代码有没有可以用更函数式风格改写的地方?比如用 map/filter/reduce 替代 for 循环。"

对比一下"命令式"和"函数式"两种写法,感受它们各自的优缺点。