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

如何在JavaScript中按service_request_id分组求和对象数组

问题描述

我有如下对象数组,希望按service_request_id进行分组,计算value字段的总和,并生成包含breakup明细的结果数组。尝试过reduce和map方法,但不清楚如何实现分组与求和,寻求帮助。

输入数组示例

let inputData = [
  {
    product_name: 'Gitlab',
    service_request_id: 1,
    request_id: 378,
    value: 10,
    fulfillment_started_at: '2022/8/9'
  },
  {
    product_name: 'Opsera',
    service_request_id: 1,
    request_id: 377,
    value: 20,
    fulfillment_started_at: '2022/8/9'
  },
  {
    product_name: 'Opsera',
    service_request_id: 2,
    request_id: 379,
    value: 20,
    fulfillment_started_at: '2022/8/9'
  }
]

期望输出结果

[
  {
    "service_request_id": 1,
    "value": 30,
    "fulfillment_started_at": "2022/8/9",
    "breakup": [
      {
        "request_id": 377,
        "category": "Opsera",
        "value": 20
      },
      {
        "request_id": 378,
        "category": "Gitlab",
        "value": 10
      }
    ]
  },
  {
    "service_request_id": 2,
    "value": 20,
    "fulfillment_started_at": "2022/8/9",
    "breakup": [
      {
        "request_id": 379,
        "category": "Opsera",
        "value": 20
      }
    ]
  }
]

注:原期望输出中service_request_id=2的value写为26,与输入数据不符,此处按输入数据计算结果为20。

当前尝试的代码

let desiredResult = [
  {
    product_name: 'Gitlab',
    service_request_id: 1,
    request_id: 378,
    value: 10,
    fulfillment_started_at: '2022/8/9'
  },
  {
    product_name: 'Opsera',
    service_request_id: 1,
    request_id: 377,
    value: 20,
    fulfillment_started_at: '2022/8/9'
  },
  {
    product_name: 'Opsera',
    service_request_id: 2,
    request_id: 379,
    value: 20,
    fulfillment_started_at: '2022/8/9'
  }
]

let final=[];
var sums = {};
for (var i = 0; i < desiredResult.length; i++) {
  var obj = desiredResult[i];
  sums[obj.service_request_id] = sums[obj.service_request_id] === undefined ? 0 : sums[obj.service_request_id];
  sums[obj.service_request_id] += parseInt(obj.difference);
    newobj={}
    newobj['service_request_id']={"total":sums[obj.service_request_id]}
    newobj['service_request_id'] = obj.service_request_id
  //  if(!Array.isArray(newobj['breakup'])) newobj['breakup']=[]
    
    final.push(newobj)
}

console.log(final);
解决方案

可以用Array.reduce()实现分组、求和与明细构建,步骤如下:

  1. 用reduce遍历输入数组,以service_request_id为键构建分组对象,存储每个分组的总和、日期及明细列表。
  2. 遍历完成后,将分组对象的值转换为数组,得到最终结果。

完整代码:

const inputData = [
  {
    product_name: 'Gitlab',
    service_request_id: 1,
    request_id: 378,
    value: 10,
    fulfillment_started_at: '2022/8/9'
  },
  {
    product_name: 'Opsera',
    service_request_id: 1,
    request_id: 377,
    value: 20,
    fulfillment_started_at: '2022/8/9'
  },
  {
    product_name: 'Opsera',
    service_request_id: 2,
    request_id: 379,
    value: 20,
    fulfillment_started_at: '2022/8/9'
  }
];

const result = Object.values(inputData.reduce((acc, item) => {
  const key = item.service_request_id;
  // 初始化分组结构(如果不存在)
  if (!acc[key]) {
    acc[key] = {
      service_request_id: key,
      value: 0,
      fulfillment_started_at: item.fulfillment_started_at,
      breakup: []
    };
  }
  // 累加value总和
  acc[key].value += item.value;
  // 添加breakup明细项
  acc[key].breakup.push({
    request_id: item.request_id,
    category: item.product_name,
    value: item.value
  });
  return acc;
}, {}));

console.log(result);

代码解释

  • reduce初始化:初始值为一个空对象,用于存储每个service_request_id对应的分组数据。
  • 分组判断:若当前service_request_id对应的分组不存在,创建包含基础结构的对象,设置初始总和为0、日期取当前项的日期、明细数组为空。
  • 求和与明细构建:遍历每项时,给对应分组的value累加当前项的value,同时将当前项转换为指定的明细格式,添加到breakup数组中。
  • 转换为数组:用Object.values()提取分组对象的所有值,转换为数组后即为期望的结果格式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 03:57:23