如何在JavaScript/TypeScript中用Lodash实现指定字段分组与求和?
分组求和实现方案
原始查询数据
const rawData = [ { INTERVIEW_DT: "20220823", DEPT_ID: "c97852f5-3d71-41ae-81f7-bb5df2a321ba", RECRUIT_COUNT: 1, INTERVIEW_CNT: 1, PASS_CNT: 0, }, { INTERVIEW_DT: "20220823", DEPT_ID: "d9608b11-fa24-4f53-bad4-0ea2cf375ade", RECRUIT_COUNT: 3, INTERVIEW_CNT: 1, PASS_CNT: 1, }, { INTERVIEW_DT: "20220824", DEPT_ID: "c97852f5-3d71-41ae-81f7-bb5df2a321ba", RECRUIT_COUNT: 5, INTERVIEW_CNT: 3, PASS_CNT: 1, }, { INTERVIEW_DT: "20220824", DEPT_ID: "d9608b11-fa24-4f53-bad4-0ea2cf375ade", RECRUIT_COUNT: 2, INTERVIEW_CNT: 2, PASS_CNT: 1, }, ];
需求说明
需要通过分组处理生成包含两个顶级键的结果:
- DATE:按
INTERVIEW_DT(日期)和DEPT_ID(部门ID)双层分组,保留各部门每日的数值 - TOTAL:忽略日期,仅按
DEPT_ID分组,汇总该部门所有日期的RECRUIT_COUNT、INTERVIEW_CNT、PASS_CNT数值
目标结果
{ 'DATE': [{ '20220823': [{ 'c97852f5-3d71-41ae-81f7-bb5df2a321ba': { 'RECRUIT_COUNT': 1, 'INTERVIEW_CNT': 1, 'PASS_CNT': 0 }, }, { 'd9608b11-fa24-4f53-bad4-0ea2cf375ade': { 'RECRUIT_COUNT': 3, 'INTERVIEW_CNT': 1, 'PASS_CNT': 1 } } ], '20220824': [{ 'c97852f5-3d71-41ae-81f7-bb5df2a321ba': { 'RECRUIT_COUNT': 5, 'INTERVIEW_CNT': 3, 'PASS_CNT': 1 }, }, { 'd9608b11-fa24-4f53-bad4-0ea2cf375ade': { 'RECRUIT_COUNT': 2, 'INTERVIEW_CNT': 2, 'PASS_CNT': 1 } } ], }], 'TOTAL': [{ 'c97852f5-3d71-41ae-81f7-bb5df2a321ba': { 'RECRUIT_COUNT': 6, 'INTERVIEW_CNT': 5, 'PASS_CNT': 1 }, }, { 'd9608b11-fa24-4f53-bad4-0ea2cf375ade': { 'RECRUIT_COUNT': 5, 'INTERVIEW_CNT': 3, 'PASS_CNT': 2 } } ] }
JavaScript实现代码
function transformData(data) { // 初始化结果结构 const result = { DATE: [{}], TOTAL: [{}] }; // 遍历原始数据,同时处理DATE和TOTAL分组 data.forEach(item => { const { INTERVIEW_DT, DEPT_ID, RECRUIT_COUNT, INTERVIEW_CNT, PASS_CNT } = item; const dateGroup = result.DATE[0]; const totalGroup = result.TOTAL[0]; // 处理DATE分组:按日期+部门存储 if (!dateGroup[INTERVIEW_DT]) { dateGroup[INTERVIEW_DT] = []; } // 检查当前部门是否已在日期分组中,不存在则添加 const deptExistsInDate = dateGroup[INTERVIEW_DT].some(obj => Object.keys(obj)[0] === DEPT_ID); if (!deptExistsInDate) { dateGroup[INTERVIEW_DT].push({ [DEPT_ID]: { RECRUIT_COUNT, INTERVIEW_CNT, PASS_CNT } }); } // 处理TOTAL分组:按部门汇总数值 if (!totalGroup[DEPT_ID]) { totalGroup[DEPT_ID] = { RECRUIT_COUNT: 0, INTERVIEW_CNT: 0, PASS_CNT: 0 }; } totalGroup[DEPT_ID].RECRUIT_COUNT += RECRUIT_COUNT; totalGroup[DEPT_ID].INTERVIEW_CNT += INTERVIEW_CNT; totalGroup[DEPT_ID].PASS_CNT += PASS_CNT; }); // 将TOTAL的对象转换为目标格式的数组(每个部门单独一个对象) result.TOTAL = Object.entries(result.TOTAL[0]).map(([deptId, stats]) => ({ [deptId]: stats })); return result; } // 调用函数并输出结果 const transformedResult = transformData(rawData); console.log(JSON.stringify(transformedResult, null, 2));
代码说明
- 初始化符合目标结构的结果对象,DATE和TOTAL初始为包含空对象的数组
- 遍历原始数据,分别处理DATE和TOTAL的分组逻辑:
- DATE部分:先检查日期分组是否存在,不存在则创建;再检查当前部门是否已在该日期分组中,不存在则添加对应的部门统计对象
- TOTAL部分:先检查部门是否已存在,不存在则初始化统计数值为0;然后累加对应字段的数值
- 最后将TOTAL的对象转换为目标要求的数组格式(每个部门对应一个单独对象)
内容的提问来源于stack exchange,提问作者GYEONGSEOP KIM
相关产品推荐
相关产品推荐

