如何在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()实现分组、求和与明细构建,步骤如下:
- 用
reduce遍历输入数组,以service_request_id为键构建分组对象,存储每个分组的总和、日期及明细列表。 - 遍历完成后,将分组对象的值转换为数组,得到最终结果。
完整代码:
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
相关产品推荐
相关产品推荐

