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

如何将年度产品销售数组按客户、产品分组为月度字段结构

问题:将客户月度销售数据整理为按客户-产品分组的年度记录

问题背景

我有一个存储了多位客户年度各月不同产品销售数据的数组,希望将每位客户的年度采购数据整理为单条记录结构。

示例数据

var sales = [
  ["Jan", "Customer 1", "Product 1", 538],
  ["Feb", "Customer 1", "Product 1", 0],
  ["March", "Customer 1", "Product 1", 252],
  ["Apr", "Customer 1", "Product 1", 0],
  ["May", "Customer 1", "Product 1", 630],
  ["June", "Customer 1", "Product 1", 945],
  ["July", "Customer 1", "Product 1", 0],
  ["Aug", "Customer 1", "Product 1", 630],
  ["Sept", "Customer 1", "Product 1", 756],
  ["Oct", "Customer 1", "Product 1", 0],
  ["Nov", "Customer 1", "Product 1", 0],
  ["Dec", "Customer 1", "Product 1", 630],
  ["Jan", "Customer 1", "Product 2", 50],
  ["Feb", "Customer 1", "Product 2", 630],
  ...
]

已尝试的代码

我已尝试获取唯一产品列表和唯一客户列表,但不知后续如何处理:

// 获取唯一产品列表
var products = sales.map(item => { return item[2]; }).filter((val, index, self) => { return self.indexOf(val) === index; });
console.log(products);
// 获取唯一客户列表
var targets = sales.map(item => { return item[1] }).filter((val, index, self) => { return self.indexOf(val) === index });
console.log(targets);

期望结果

我期望得到按客户、产品分组的对象数组,格式如下:

[
  {
    "customer": "Customer 1",
    "product": "Product 1",
    "jan": 538,
    "feb": 0,
    "march": 252,
    ...
  },
  {
    "customer": "Customer 1",
    "product": "Product 2",
    "jan": 50,
    "feb": 630,
    ...
  }
]

实现思路与代码

其实核心思路很简单:按「客户+产品」的组合作为唯一标识来分组,把每个月的销售额数据挂载到对应的分组对象里就行。不用先单独提取客户和产品列表再嵌套循环,这样效率更高,只需要遍历原始数组一次就能搞定。

具体步骤

  1. 先创建一个临时对象(比如叫groupedData),用来暂存每个客户+产品的组合数据,用客户名_产品名作为键,避免重复分组;
  2. 遍历原始的sales数组,对每一条数据做如下处理:
    • 提取出月份、客户、产品、销售额这四个值;
    • 把月份转成小写(和你期望结果里的键名保持一致);
    • 生成唯一的分组键,比如${customer}_${product};
    • 如果这个分组键在临时对象里不存在,就先初始化一个包含customer和product属性的基础对象;
    • 把当前月份的销售额添加到这个基础对象里,键就是小写的月份名;
  3. 遍历完成后,用Object.values(groupedData)把临时对象里的所有值提取出来,就是你要的数组格式了。

完整可运行代码

var sales = [
  ["Jan", "Customer 1", "Product 1", 538],
  ["Feb", "Customer 1", "Product 1", 0],
  ["March", "Customer 1", "Product 1", 252],
  ["Apr", "Customer 1", "Product 1", 0],
  ["May", "Customer 1", "Product 1", 630],
  ["June", "Customer 1", "Product 1", 945],
  ["July", "Customer 1", "Product 1", 0],
  ["Aug", "Customer 1", "Product 1", 630],
  ["Sept", "Customer 1", "Product 1", 756],
  ["Oct", "Customer 1", "Product 1", 0],
  ["Nov", "Customer 1", "Product 1", 0],
  ["Dec", "Customer 1", "Product 1", 630],
  ["Jan", "Customer 1", "Product 2", 50],
  ["Feb", "Customer 1", "Product 2", 630]
];

function groupSalesData(sales) {
  const groupedData = {};
  
  sales.forEach(item => {
    // 解构提取数据,也可以用item[0], item[1]这种方式,看你习惯
    const [month, customer, product, amount] = item;
    // 转成小写的月份键
    const monthKey = month.toLowerCase();
    // 生成唯一分组标识
    const groupKey = `${customer}_${product}`;
    
    // 初始化分组对象(如果不存在的话)
    if (!groupedData[groupKey]) {
      groupedData[groupKey] = {
        customer: customer,
        product: product
      };
    }
    
    // 挂载当月销售额
    groupedData[groupKey][monthKey] = amount;
  });
  
  // 把对象转换为数组返回
  return Object.values(groupedData);
}

// 调用函数并查看结果
const formattedSales = groupSalesData(sales);
console.log(formattedSales);

小补充

  • 如果你的客户名或产品名里可能包含下划线,可以换用其他分隔符,比如|,只要能保证「客户+分隔符+产品」的组合唯一就没问题;
  • 要是需要兼容ES5及以下的旧环境,只需要把解构赋值改成普通的变量提取:const month = item[0]; const customer = item[1]; ... 就行,其他逻辑完全不变。

内容的提问来源于stack exchange,提问作者P.Gichia

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:37:22