JS中如何按条件为科目成绩数据添加含值对象数组?
科目成绩数据结构化解决方案
问题描述
我有一个包含学生科目成绩的对象,需要按键名进行数据结构化:每个科目分为第1部分(part_1)和第2部分(part_2),每部分需包含MCQ、CQ、total字段(部分科目没有MCQ,比如English)。目前卡在怎么给各科目部分添加对应值到对象数组里,现有代码生成不了预期输出,具体代码和预期输出如下:
现有代码
const result = { id: 427, merit: "1", name: "Israt Jahan", group_name: "business", GPA: "4.4", english_1st_CQ: "24", english_1st_total: "24", english_2nd_CQ: "24", english_2nd_total: "24", english_GP: "2", english_percentage: "48", english_total: "48", production_1st_CQ: "32", production_1st_MCQ: "11", production_1st_total: "43", production_2nd_CQ: "26", production_2nd_MCQ: "11", production_2nd_total: "37", production_GP: "5", production_percentage: "80", roll: 1401, total_failed: "0", total_gp: "24", total_marks: "439", }; const subjectAdd = (arr, title) => { const node = arr.find((node) => node.subject === title) ?? { subject: title.split(" ")[0], part_1: [], part_2: [], }; if (arr.every((e) => e.subject !== node.subject)) arr.push(node); return node; }; const subjects = (data) => { const subject = []; Object.entries(data).map(([key, value]) => { const [subjectName, subjectPosition, suffix] = key.split("_"); if ( subjectName != "id" && subjectName != "date" && subjectName != "group" && subjectName != "roll" && subjectName != "name" && subjectName != "merit" && subjectName != "GPA" && subjectName != "total" ) { const newSubject = subjectAdd(subject, `${subjectName} ${subjectPosition}`); const part1 = subjectAdd(newSubject.part_1, `${subjectName} ${subjectPosition}`); const part2 = subjectAdd(newSubject.part_2, `${subjectName} ${subjectPosition}`); } }); return subject; }; console.log("result", subjects(result));
预期输出
[ { "subject": "english", "part_1": [ { "subject": "english 1st", "CQ": 24, "total": 24 } ], "part_2": [ { "subject": "english 2nd", "CQ": 24, "total": 24 } ] }, { "subject": "production", "part_1": [ { "subject": "production 1st", "MCQ": 11, "CQ": 32, "total": 43 } ], "part_2": [ { "subject": "production 2nd", "MCQ": 11, "CQ": 26, "total": 37 } ] } ]
解决方法
原代码的核心问题在于subjectAdd函数职责混淆,以及未正确将字段值映射到对应科目部分的属性中。以下是修正后的代码:
const result = { id: 427, merit: "1", name: "Israt Jahan", group_name: "business", GPA: "4.4", english_1st_CQ: "24", english_1st_total: "24", english_2nd_CQ: "24", english_2nd_total: "24", english_GP: "2", english_percentage: "48", english_total: "48", production_1st_CQ: "32", production_1st_MCQ: "11", production_1st_total: "43", production_2nd_CQ: "26", production_2nd_MCQ: "11", production_2nd_total: "37", production_GP: "5", production_percentage: "80", roll: 1401, total_failed: "0", total_gp: "24", total_marks: "439", }; // 获取或创建科目对象 const getOrCreateSubject = (subjects, subjectName) => { let subject = subjects.find(s => s.subject === subjectName); if (!subject) { subject = { subject: subjectName, part_1: [], part_2: [] }; subjects.push(subject); } return subject; }; // 获取或创建科目下的部分条目(1st/2nd) const getOrCreatePartItem = (part, subjectFullName) => { let item = part.find(i => i.subject === subjectFullName); if (!item) { item = { subject: subjectFullName }; part.push(item); } return item; }; const subjects = (data) => { const subjectList = []; // 定义需要忽略的非科目字段 const ignoreFields = new Set(['id', 'merit', 'name', 'group_name', 'GPA', 'roll', 'total_failed', 'total_gp', 'total_marks']); Object.entries(data).forEach(([key, value]) => { const parts = key.split("_"); // 只处理符合 科目_部分_类型 格式的字段 if (parts.length === 3 && !ignoreFields.has(parts[0])) { const [subjectName, partSuffix, field] = parts; const subjectFullName = `${subjectName} ${partSuffix}`; const subject = getOrCreateSubject(subjectList, subjectName); // 判断是part_1还是part_2 const targetPart = partSuffix === '1st' ? subject.part_1 : subject.part_2; const partItem = getOrCreatePartItem(targetPart, subjectFullName); // 将值转为数字,赋值到对应字段 partItem[field.toUpperCase()] = parseInt(value, 10); } }); return subjectList; }; console.log(JSON.stringify(subjects(result), null, 2));
关键改进点
- 拆分职责:把获取科目对象和科目部分条目的逻辑拆成独立函数,避免逻辑混乱
- 精准过滤:用
Set存储忽略字段,只处理科目_部分_类型格式的有效键 - 正确映射:根据
1st/2nd定位到part_1/part_2,将字段值转为数字后赋值到对应属性 - 动态创建:自动创建不存在的科目或科目部分条目,确保结构完整
运行修正后的代码即可得到预期输出。
内容的提问来源于stack exchange,提问作者Anik Ahmed fathe
相关产品推荐
相关产品推荐

