期末考试结束不久,辛勤的园丁们就将所有学生的考试成绩汇总完毕。不过现在遇到一个问题,那就是目前所有学生的考试数据均混杂在一起。这些数据结构如下:
[
{
name: "潇然",
class: 2, // 班级
math: 110, // 数学成绩
language: 92, // 语文成绩
english: 114, // 英语成绩
physics: 56, // 物理成绩
chemistry: 74, // 化学成绩
},
{
name: "张三",
class: 1,
math: 100,
language: 80,
english: 60,
physics: 80,
chemistry: 60,
},
// ...
];
从上面的数据结构来看,老师们很难从中分辨出自己班级的学生,更不用说班级学生的成绩排名了。因此我们需要封装一个用于处理这些数据对工具函数,以便帮助老师们更好的查看自己班级的学生成绩。
本题已经内置了初始代码,打开实验环境,目录结构如下:
├── index.html
└── student-grade.js
其中:
index.html
是主页面。student-grade.js
是待补充的 js 文件。补充文件 student-grade.js
中的 orderStudentGrade
工具函数,访问 index.html
页面会按照不同的班级,且班级内降序排列所有学生的成绩。最终效果如下:
具体功能说明:
// 返回的结果对象:
// key 是班级号,同一个班级中学生成绩降序排列
{
1: [
{
name: "潇然",
class: 1,
math: 110,
language: 92,
english: 114,
physics: 56,
chemistry: 74,
},
{
name: "张三",
class: 1,
math: 10,
language: 8,
english: 60,
physics: 8,
chemistry: 60,
},
// ...
],
2: [
// ...
],
};
student-grade.js
中指定区域答题,不能修改 index.html
中的任何代码。student-grade.js
以及 index.html
文件的文件路径以及文件名。function orderStudentGrade(students) {
// 如果传入的学生成绩列表为空,则返回一个空对象
if (students.length === 0) {
return {};
}
const result = {};
// 遍历所有学生
students.forEach(student => {
const cls = student.class;
// 如果该班级还没有在结果对象中,初始化一个空数组
if (!result[cls]) {
result[cls] = [];
}
// 将学生添加到对应的班级数组中
result[cls].push(student);
});
// 对每个班级的学生按照总分降序排列
Object.keys(result).forEach(cls => {
result[cls].sort((a, b) => {
const totalA = a.math + a.language + a.english + a.physics + a.chemistry;
const totalB = b.math + b.language + b.english + b.physics + b.chemistry;
return totalB - totalA;
});
});
return result;
}
module.exports = orderStudentGrade; // 检测需要,请勿删除
//index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>考试成绩排序</title>
</head>
<style>
#output-container {
width: 600px;
margin: 0 auto;
}
.cls {
display: flex;
flex-direction: column;
}
.cls + .cls {
margin-top: 30px;
}
.cls-header {
font-size: 30px;
}
td {
text-align: center;
}
</style>
<body>
<div id="output-container"></div>
<script>
module = {};
</script>
<script
type="text/javascript"
src="./student-grade.js
"
></script>
<script>
const orderStudentGradeFn = module.exports;
const output = document.getElementById("output-container");
const students = [
{
name: "张三",
class: 1,
math: 100,
language: 80,
english: 60,
physics: 80,
chemistry: 60,
},
{
name: "李四",
class: 1,
math: 120,
language: 60,
english: 20,
physics: 100,
chemistry: 100,
},
{
name: "王五",
class: 1,
math: 140,
language: 90,
english: 120,
physics: 60,
chemistry: 60,
},
{
name: "苑博",
class: 2,
math: 140,
language: 90,
english: 120,
physics: 60,
chemistry: 60,
},
{
name: "文轩",
class: 2,
math: 110,
language: 60,
english: 120,
physics: 30,
chemistry: 30,
},
{
name: "聪健",
class: 3,
math: 110,
language: 60,
english: 120,
physics: 30,
chemistry: 30,
},
{
name: "烨磊",
class: 3,
math: 88,
language: 70,
english: 100,
physics: 45,
chemistry: 56,
},
{
name: "烨霖",
class: 3,
math: 120,
language: 60,
english: 100,
physics: 50,
chemistry: 60,
},
{
name: "荣轩",
class: 2,
math: 90,
language: 160,
english: 120,
physics: 50,
chemistry: 50,
},
{
name: "懿轩",
class: 2,
math: 100,
language: 90,
english: 120,
physics: 90,
chemistry: 90,
},
{
name: "擎苍",
class: 2,
math: 100,
language: 130,
english: 120,
physics: 10,
chemistry: 40,
},
{
name: "绍齐",
class: 1,
math: 100,
language: 90,
english: 120,
physics: 60,
chemistry: 60,
},
{
name: "皓轩",
class: 1,
math: 100,
language: 120,
english: 120,
physics: 50,
chemistry: 50,
},
{
name: "鹭洋",
class: 1,
math: 100,
language: 80,
english: 120,
physics: 30,
chemistry: 90,
},
{
name: "潇然",
class: 2,
math: 110,
language: 92,
english: 114,
physics: 56,
chemistry: 74,
},
{
name: "智宸",
class: 1,
math: 100,
language: 100,
english: 100,
physics: 30,
chemistry: 30,
},
{
name: "风华",
class: 1,
math: 110,
language: 60,
english: 120,
physics: 80,
chemistry: 79,
},
{
name: "雨泽",
class: 1,
math: 100,
language: 68,
english: 115,
physics: 36,
chemistry: 83,
},
{
name: "浩然",
class: 2,
math: 105,
language: 116,
english: 120,
physics: 90,
chemistry: 60,
},
{
name: "瑾瑜",
class: 3,
math: 110,
language: 60,
english: 120,
physics: 99,
chemistry: 98,
},
];
const result = orderStudentGradeFn(students);
Object.keys(result).forEach((cls) => {
const clsContainer = document.createElement("div");
clsContainer.className = "cls";
const clsHeader = document.createElement("div");
clsHeader.className = "cls-header";
clsHeader.innerText = `第${cls}班`;
clsContainer.appendChild(clsHeader);
const table = document.createElement("table");
table.border = 1;
table.align = "center";
table.width = "100%";
const header = document.createElement("tr");
const th1 = document.createElement("th");
th1.innerText = "姓名";
header.appendChild(th1);
const th2 = document.createElement("th");
th2.innerText = "语文";
header.appendChild(th2);
const th3 = document.createElement("th");
th3.innerText = "数学";
header.appendChild(th3);
const th4 = document.createElement("th");
th4.innerText = "英语";
header.appendChild(th4);
const th5 = document.createElement("th");
th5.innerText = "物理";
header.appendChild(th5);
const th6 = document.createElement("th");
th6.innerText = "化学";
header.appendChild(th6);
const th7 = document.createElement("th");
th7.innerText = "总分";
header.appendChild(th7);
table.appendChild(header);
const students = result[cls];
students.forEach((student) => {
const tr = document.createElement("tr");
const td1 = document.createElement("td");
td1.innerText = student.name;
tr.appendChild(td1);
const td2 = document.createElement("td");
td2.innerText = student.language;
tr.appendChild(td2);
const td3 = document.createElement("td");
td3.innerText = student.math;
tr.appendChild(td3);
const td4 = document.createElement("td");
td4.innerText = student.english;
tr.appendChild(td4);
const td5 = document.createElement("td");
td5.innerText = student.physics;
tr.appendChild(td5);
const td6 = document.createElement("td");
td6.innerText = student.chemistry;
tr.appendChild(td6);
const td7 = document.createElement("td");
td7.innerText =
student.math +
student.language +
student.english +
student.physics +
student.chemistry;
tr.appendChild(td7);
table.appendChild(tr);
});
clsContainer.appendChild(table);
output.appendChild(clsContainer);
});
</script>
</body>
</html>
<!DOCTYPE html>
声明文档类型为 HTML5。<html lang="en">
设置页面语言为英语。<head>
标签中: <meta charset="UTF-8" />
指定字符编码为 UTF - 8。<meta http-equiv="X-UA-Compatible" content="IE=edge" />
确保页面在 Internet Explorer 中以最新版本的渲染引擎显示。<meta name="viewport" content="width=device-width, initial-scale=1.0" />
使页面在不同设备上能正确显示。<title>考试成绩排序</title>
设置页面标题。<style>
标签内定义了页面的样式,包括输出容器的宽度和居中显示,班级容器的布局,班级标题的字体大小,以及表格单元格内容的居中显示。<div id="output-container"></div>
创建一个 div
元素,作为后续展示排序结果的容器。<script>module = {};</script>
模拟 Node.js 的模块系统,创建一个空的 module
对象,以便后续引入并使用 student-grade.js
中的导出函数。<script type="text/javascript" src="./student-grade.js"></script>
引入外部 JavaScript 文件 student-grade.js
,该文件包含了实现学生成绩排序的核心逻辑。const orderStudentGradeFn = module.exports;
从 module.exports
中获取 student-grade.js
导出的排序函数。const output = document.getElementById("output-container");
获取之前创建的输出容器元素。students
数组,包含多个学生的信息对象,每个对象有姓名、班级和各科成绩。const result = orderStudentGradeFn(students);
调用排序函数对学生数据进行处理,得到按班级分组且组内按总分降序排列的结果。Object.keys(result).forEach
遍历排序结果的每个班级: div
元素作为班级容器,并添加 cls
类名。div
元素作为班级标题,显示班级编号,并添加到班级容器中。table
元素用于展示该班级学生的成绩信息,设置表格的边框、对齐方式和宽度。//student-grade.js
function orderStudentGrade(students) {
// 如果传入的学生成绩列表为空,则返回一个空对象
if (students.length === 0) {
return {};
}
const result = {};
// 遍历所有学生
students.forEach(student => {
const cls = student.class;
// 如果该班级还没有在结果对象中,初始化一个空数组
if (!result[cls]) {
result[cls] = [];
}
// 将学生添加到对应的班级数组中
result[cls].push(student);
});
// 对每个班级的学生按照总分降序排列
Object.keys(result).forEach(cls => {
result[cls].sort((a, b) => {
const totalA = a.math + a.language + a.english + a.physics + a.chemistry;
const totalB = b.math + b.language + b.english + b.physics + b.chemistry;
return totalB - totalA;
});
});
return result;
}
module.exports = orderStudentGrade; // 检测需要,请勿删除
1. 函数定义与空数组检查
function orderStudentGrade(students) {
if (students.length === 0) {
return {};
}
orderStudentGrade
是一个函数,它接收一个参数 students
,该参数是一个包含多个学生信息对象的数组。if (students.length === 0)
用于检查传入的 students
数组是否为空。如果为空,函数会直接返回一个空对象 {}
,因为没有学生数据可供处理。const result = {};
result
是一个空对象,用于存储按班级分组后的学生数据。后续代码会将每个班级的学生信息存储在这个对象的对应属性中。students.forEach(student => {
const cls = student.class;
if (!result[cls]) {
result[cls] = [];
}
result[cls].push(student);
});
students.forEach(student => { ... })
:使用 forEach
方法遍历 students
数组中的每个学生对象。const cls = student.class
:从当前学生对象中获取其所在的班级编号。if (!result[cls])
:检查 result
对象中是否已经存在以该班级编号为属性名的数组。如果不存在,就为该班级初始化一个空数组。result[cls].push(student)
:将当前学生对象添加到对应班级的数组中。Object.keys(result).forEach(cls => {
result[cls].sort((a, b) => {
const totalA = a.math + a.language + a.english + a.physics + a.chemistry;
const totalB = b.math + b.language + b.english + b.physics + b.chemistry;
return totalB - totalA;
});
});
Object.keys(result).forEach(cls => { ... })
:使用 Object.keys
方法获取 result
对象的所有属性名(即班级编号),然后遍历这些班级编号。result[cls].sort((a, b) => { ... })
:对每个班级的学生数组使用 sort
方法进行排序。sort
方法接收一个比较函数作为参数,该函数用于确定元素的排序顺序。const totalA = a.math + a.language + a.english + a.physics + a.chemistry
和 const totalB = b.math + b.language + b.english + b.physics + b.chemistry
:分别计算学生 a
和学生 b
的总分。return totalB - totalA
:根据总分降序排序。如果 totalB
大于 totalA
,返回一个正数,b
会排在 a
前面;如果 totalB
小于 totalA
,返回一个负数,a
会排在 b
前面;如果两者相等,返回 0,元素顺序不变。return result;
result
对象,该对象包含了按班级分组并在每个班级内按总分降序排序后的学生数据。module.exports = orderStudentGrade;
orderStudentGrade
函数导出,以便其他文件可以引入并使用这个函数。这是 Node.js 中常用的模块导出方式。通过以上步骤,代码实现了将学生按班级分组,并在每个班级内按总分降序排序的功能。
三、工作流程 ▶️
student-grade.js
文件,准备调用其中的排序函数。student-grade.js
导出的 orderStudentGrade
函数。orderStudentGrade
函数将学生按班级分组,再在每个班级内按总分降序排序,返回处理后的结果对象。通过上述流程,最终实现 “分阵营(按班级分组),比高低(按总分排序)” 的功能。