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

如何修复ES6 reduce按产品求和的结构问题并校验容量限制

产品容量求和与限制校验的实现问题

原始数据与需求

输入数据

// 二维产品数组
const products = [
  [{product: "a", volume: 3}, {product: "b", volume: 7}, {product: "c", volume: 5}],
  [{product: "a", volume: 8}, {product: "b", volume: 10}, {product: "c", volume: 4}]
];

// 产品容量限制
const ProductLimits: ProductVolumes[] = [
  {product: "a", volume: 10}, 
  {product: "b", volume: 22}, 
  {product: "c", volume: 12}
];

需求

  • 将二维产品数组扁平化后,按产品名称对volume求和
  • 确保每个产品的总容量不超过ProductLimits中对应的限制值

当前实现问题

已通过flatMap将二维数组扁平化,得到一维数组:

[
  {product: "a", volume: 3}, {product: "b", volume: 7}, {product: "c", volume: 5},
  {product: "a", volume: 8}, {product: "b", volume: 10}, {product: "c", volume: 4}
]

但后续使用reduce求和时,因初始值结构错误,导致结果异常:

// 错误的reduce实现与接口
interface IInterface {
  product: string;
  volume: number;
  [product: string]: any;
}

products.flatMap(x => x.map(y => ({ product: y.product, volume: y.volume })))
  .reduce((acc: IInterface, i) => {
    acc[i.product] = (acc[i.product] || 0) + i.volume;
    return acc;
  });

迭代3次后得到异常结构:

product: "a"
volume: 3
b: 7
c: 5

问题根因:reduce未显式指定初始值时,默认取数组第一个元素作为初始累加器,且IInterface的设计错误——不需要固定的product和volume属性,应该是纯索引签名的对象,用来存储每个产品的总容量。

修复方案

步骤1:修正reduce初始值与接口

将IInterface改为纯索引签名的对象,同时给reduce指定空对象作为初始值:

// 修正后的接口:存储产品名到总容量的映射
interface ProductTotalMap {
  [productName: string]: number;
}

const productTotals = products.flatMap(group => group)
  .reduce((acc: ProductTotalMap, item) => {
    acc[item.product] = (acc[item.product] || 0) + item.volume;
    return acc;
  }, {} as ProductTotalMap);

此时得到正确的求和结果:

{ a: 11, b: 17, c: 9 }

步骤2:添加容量限制校验

先将ProductLimits转换为对象映射,方便快速查找限制值,再遍历求和结果进行校验:

// 将限制数组转为对象映射
const limitMap = ProductLimits.reduce((map, limit) => {
  map[limit.product] = limit.volume;
  return map;
}, {} as ProductTotalMap);

// 校验每个产品的总容量是否超过限制
const validatedTotals = Object.entries(productTotals).map(([product, total]) => {
  const maxVolume = limitMap[product];
  return {
    product,
    totalVolume: total,
    maxVolume,
    isOverLimit: total > maxVolume
  };
});

最终校验结果示例:

[
  { product: "a", totalVolume: 11, maxVolume: 10, isOverLimit: true },
  { product: "b", totalVolume: 17, maxVolume: 22, isOverLimit: false },
  { product: "c", totalVolume: 9, maxVolume: 12, isOverLimit: false }
]

更优实现(一步完成求和与校验)

可以合并扁平化、求和、校验逻辑,减少中间变量:

const limitMap = ProductLimits.reduce((map, item) => {
  map[item.product] = item.volume;
  return map;
}, {} as Record<string, number>);

const result = products.flat()
  .reduce((acc, item) => {
    // 累加容量
    const currentTotal = (acc[item.product]?.totalVolume || 0) + item.volume;
    // 对比限制
    acc[item.product] = {
      product: item.product,
      totalVolume: currentTotal,
      maxVolume: limitMap[item.product],
      isOverLimit: currentTotal > limitMap[item.product]
    };
    return acc;
  }, {} as Record<string, { product: string; totalVolume: number; maxVolume: number; isOverLimit: boolean }>);

// 转为数组格式(可选)
const resultArray = Object.values(result);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 00:15:17