JavaScript自定义元素分组:第1/4组8个,第2/3/5组7个
问题描述
现有Node.js代码读取timetable.csv文件,筛选指定班级的课程数据并排序后,通过reduce方法将数据按每组8个分组。实际需求为:第1组和第4组各含8个元素,第2、3、5组各含7个元素。尝试条件判断等方法未成功,求可行解决方案。
原代码
const fs = require("fs"); const { parse } = require("csv-parse"); function getSchedule() { let schedule = []; fs.createReadStream("./timetable.csv") .pipe(parse({ delimiter: ",", from_line: 2 })) .on("data", function (row) { let classp = "ΘΗΨ3β"; // 获取指定班级的所有课程数据 for (let i = 0; i < row.length; i++) { if (row[i].includes(classp) || row[i].includes("ΓΘ2Φ5-3") || row[i].includes("ΓΘ1Μ7-3")) { schedule.push({ number: i, text: row[i] }); } } // 手动排序数据 for (let i = 0; i < schedule.length; i++) { if (schedule[i + 1]) { if (schedule[i].number > schedule[i + 1].number) { let temp = schedule[i]; schedule[i] = schedule[i + 1]; schedule[i + 1] = temp; } } } let numberOfObjects = 8 // 控制每组元素数量 // 将数据按每组8个分组 let groupedProducts = schedule.reduce((acc, elem, index) => { let rowNum = Math.floor(index / numberOfObjects) + 1; acc[`${rowNum}`] = acc[`${rowNum}`] || []; acc[`${rowNum}`].push(elem); return acc }, {}); console.log(groupedProducts) }); } getSchedule();
原输出
{ '1': [ { number: 3, text: 'ΓΘ1Μ7-3 / 16 / Μαθηματικά Εμβ. 4-ωρ 04ΓΘΚ' }, { number: 4, text: 'ΘΗΨ3β / 24 / Ψηφ.Ηλεκτρονικά II Γ ΘΗΥ' }, { number: 5, text: 'ΘΗΨ3β / 24 / Ψηφ.Ηλεκτρονικά II Γ ΘΗΥ' }, { number: 6, text: 'ΓΘ2Φ5-3 / 53 / Φυσική ΘΓΚ3-Μ6' }, { number: 7, text: 'ΘΗΨ3β / 11 / Νέα Ελληνικά ΘΓΚ3-Μ1 Γ' }, { number: 8, text: 'ΘΗΨ3β / 11 / Νέα Ελληνικά ΘΓΚ3-Μ1 Γ' }, { number: 9, text: 'ΘΗΨ3β / 138α / Θρησκευτικά ΘΓΚ3-Μ1 Γ' }, { number: 10, text: 'ΘΗΨ3β / 118 / Εφαρμ.Προγραμ. ΙΙΙ Γ ΘΗΨ' } ], ..... '5': [ { number: 37, text: 'ΓΘ1Μ7-3 / 16 / Μαθηματικά Εμβ. 4-ωρ 04ΓΘΚ' }, { number: 39, text: 'ΘΗΨ3β / 112 / Μικροελ. Ρομποτική Γ ΘΗΨ' }, { number: 40, text: 'ΘΗΨ3β / 118 / Εφαρμ.Προγραμ. ΙΙΙ Γ ΘΗΨ' }, { number: 41, text: 'ΘΗΨ3β / 118 / Εφαρμ.Προγραμ. ΙΙΙ Γ ΘΗΨ' } ] }
解决方案
核心思路
放弃固定每组数量的计算方式,直接定义各分组的元素数量规则,通过累计分组边界的方式,快速判断每个元素所属的分组,确保严格符合需求。
修改后的代码
const fs = require("fs"); const { parse } = require("csv-parse"); function getSchedule() { let schedule = []; fs.createReadStream("./timetable.csv") .pipe(parse({ delimiter: ",", from_line: 2 })) .on("data", function (row) { let classp = "ΘΗΨ3β"; // 筛选指定班级的课程数据 for (let i = 0; i < row.length; i++) { if (row[i].includes(classp) || row[i].includes("ΓΘ2Φ5-3") || row[i].includes("ΓΘ1Μ7-3")) { schedule.push({ number: i, text: row[i] }); } } // 优化排序:用内置sort方法替代手动冒泡 schedule.sort((a, b) => a.number - b.number); // 定义每组的元素数量:第1组8个,第2、3组7个,第4组8个,第5组7个 const groupSizes = [8,7,7,8,7]; // 计算分组累计边界,用于快速定位元素所属分组 const groupBounds = groupSizes.reduce((acc, size, idx) => { const prevTotal = acc[idx] || 0; acc.push(prevTotal + size); return acc; }, []); // 按规则分组 let groupedProducts = schedule.reduce((acc, elem, index) => { // 找到当前元素对应的分组索引 const groupIndex = groupBounds.findIndex(bound => index < bound); const groupKey = `${groupIndex + 1}`; acc[groupKey] = acc[groupKey] || []; acc[groupKey].push(elem); return acc; }, {}); console.log(groupedProducts) }); } getSchedule();
关键修改说明
- 排序优化:将低效的手动冒泡排序替换为
Array.sort(),按number字段升序排列,代码更简洁高效。 - 规则明确化:用
groupSizes数组直接定义每组的元素数量,直观对应需求,便于后续调整。 - 边界计算:通过
reduce生成groupBounds数组(示例值为[8,15,22,30,37]),每个值代表前n组的总元素数,用于快速判断元素归属。 - 分组判断:使用
findIndex定位当前元素所在的分组,确保每个分组严格遵循设定的元素数量。
内容的提问来源于stack exchange,提问作者ImDarkk
相关产品推荐
相关产品推荐

