为数组添加countBatch与countGroup属性:仅批次首项显示批次计数
解决JavaScript数组中仅在批次首项显示countBatch的问题
问题背景
我有一个包含BatchNumber(批次号)和GroupCode(组编码)的JavaScript数组,已经完成了排序、按「批次+组」分组,并且给每组的第一个元素加上了countGroup属性(值为组内元素总数,其余元素该属性为null),同时统计了每个批次的总元素数。
目前遇到的问题是:countBatch(批次总数量)会在每个组的首项都显示,但我需要只在每个批次的第一条数据里显示countBatch,其他元素的这个属性都设为null。
现有代码、当前输出与预期输出
现有实现代码
// 示例原始数据 const originalData = [ { BatchNumber: 'B001', GroupCode: 'G1', value: 1 }, { BatchNumber: 'B001', GroupCode: 'G1', value: 2 }, { BatchNumber: 'B001', GroupCode: 'G2', value: 3 }, { BatchNumber: 'B002', GroupCode: 'G1', value: 4 }, { BatchNumber: 'B002', GroupCode: 'G2', value: 5 }, ]; // 按批次和组排序 const sortedData = [...originalData].sort((a, b) => { if (a.BatchNumber !== b.BatchNumber) return a.BatchNumber.localeCompare(b.BatchNumber); return a.GroupCode.localeCompare(b.GroupCode); }); // 统计各批次总元素数 const batchTotal = sortedData.reduce((acc, item) => { acc[item.BatchNumber] = (acc[item.BatchNumber] || 0) + 1; return acc; }, {}); // 处理分组、countGroup和countBatch const processedData = sortedData.reduce((acc, item, index, array) => { const prevItem = array[index - 1]; // 组首项赋值countGroup,其余为null const countGroup = (!prevItem || prevItem.GroupCode !== item.GroupCode) ? array.filter(i => i.BatchNumber === item.BatchNumber && i.GroupCode === item.GroupCode).length : null; // 当前问题:每个组的首项都加了countBatch const countBatch = (!prevItem || prevItem.BatchNumber !== item.BatchNumber) ? batchTotal[item.BatchNumber] : null; acc.push({ ...item, countGroup, countBatch }); return acc; }, []); console.log(processedData);
当前输出(不符合预期)
[ { BatchNumber: 'B001', GroupCode: 'G1', value: 1, countGroup: 2, countBatch: 3 }, { BatchNumber: 'B001', GroupCode: 'G1', value: 2, countGroup: null, countBatch: null }, { BatchNumber: 'B001', GroupCode: 'G2', value: 3, countGroup: 1, countBatch: 3 }, // 此处不该显示countBatch { BatchNumber: 'B002', GroupCode: 'G1', value: 4, countGroup: 1, countBatch: 2 }, { BatchNumber: 'B002', GroupCode: 'G2', value: 5, countGroup: 1, countBatch: 2 }, // 此处不该显示countBatch ]
预期输出
[ { BatchNumber: 'B001', GroupCode: 'G1', value: 1, countGroup: 2, countBatch: 3 }, { BatchNumber: 'B001', GroupCode: 'G1', value: 2, countGroup: null, countBatch: null }, { BatchNumber: 'B001', GroupCode: 'G2', value: 3, countGroup: 1, countBatch: null }, // 此处countBatch为null { BatchNumber: 'B002', GroupCode: 'G1', value: 4, countGroup: 1, countBatch: 2 }, { BatchNumber: 'B002', GroupCode: 'G2', value: 5, countGroup: 1, countBatch: null }, // 此处countBatch为null ]
解决方案
核心问题是之前的逻辑把「组的首项」和「批次的首项」混在了一起,现在需要单独跟踪批次的首次出现,只有在批次的第一个元素才赋值countBatch。
修改后的代码
// 示例原始数据 const originalData = [ { BatchNumber: 'B001', GroupCode: 'G1', value: 1 }, { BatchNumber: 'B001', GroupCode: 'G1', value: 2 }, { BatchNumber: 'B001', GroupCode: 'G2', value: 3 }, { BatchNumber: 'B002', GroupCode: 'G1', value: 4 }, { BatchNumber: 'B002', GroupCode: 'G2', value: 5 }, ]; // 1. 按批次、组排序 const sortedData = [...originalData].sort((a, b) => { if (a.BatchNumber !== b.BatchNumber) return a.BatchNumber.localeCompare(b.BatchNumber); return a.GroupCode.localeCompare(b.GroupCode); }); // 2. 统计各批次总元素数 const batchTotal = sortedData.reduce((acc, item) => { acc[item.BatchNumber] = (acc[item.BatchNumber] || 0) + 1; return acc; }, {}); // 3. 处理分组、countGroup和countBatch let lastProcessedBatch = null; // 跟踪上一个处理过的批次号 const processedData = sortedData.reduce((acc, item, index, array) => { const prevItem = array[index - 1]; // 处理countGroup:组首项赋值,其余为null const countGroup = (!prevItem || prevItem.GroupCode !== item.GroupCode) ? array.filter(i => i.BatchNumber === item.BatchNumber && i.GroupCode === item.GroupCode).length : null; // 处理countBatch:仅当当前是新批次的第一个元素时赋值,其余为null const countBatch = item.BatchNumber !== lastProcessedBatch ? batchTotal[item.BatchNumber] : null; // 更新跟踪的批次号 if (item.BatchNumber !== lastProcessedBatch) { lastProcessedBatch = item.BatchNumber; } acc.push({ ...item, countGroup, countBatch }); return acc; }, []); console.log(processedData);
代码说明
- 新增
lastProcessedBatch变量,用来记录已经处理过的批次号,确保只有当当前元素属于从未处理过的新批次时,才赋值countBatch。 - 调整
countBatch的判断逻辑:不再依赖前一个元素的批次号,而是直接对比当前批次号和lastProcessedBatch,首次出现新批次时赋值,否则设为null。 - 每次处理完新批次的第一个元素后,更新
lastProcessedBatch为当前批次号,后续同批次的所有元素都会跳过countBatch的赋值。
运行这段代码后,就能得到符合预期的输出结果。
内容的提问来源于stack exchange,提问作者Keyboard Corporation
相关产品推荐
相关产品推荐

