You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为数组添加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);

代码说明

  1. 新增lastProcessedBatch变量,用来记录已经处理过的批次号,确保只有当当前元素属于从未处理过的新批次时,才赋值countBatch。
  2. 调整countBatch的判断逻辑:不再依赖前一个元素的批次号,而是直接对比当前批次号和lastProcessedBatch,首次出现新批次时赋值,否则设为null。
  3. 每次处理完新批次的第一个元素后,更新lastProcessedBatch为当前批次号,后续同批次的所有元素都会跳过countBatch的赋值。

运行这段代码后,就能得到符合预期的输出结果。


内容的提问来源于stack exchange,提问作者Keyboard Corporation

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 12:23:22