如何将for循环改写为reduce实现按名称分组并对指定列求和
按岗位分组聚合数组实现方案
需求描述
- 按数组每行下标为1的岗位名称作为分组依据,相同岗位的行合并
- 合并时下标为2、5的列数值累加,其余列保留同分组第一行的值
- 要求避免修改原数组,使用
reduce相关方法实现
示例输入
[ [ 20, 'AJUDANTE GERAL ', 2, 'HH', 6.36, 12.72, '', '' ], [ 20, 'AJUDANTE GERAL ', 8, 'HH', 6.36, 50.88, '', '' ], [ 20, 'AJUDANTE GERAL ', 0.15, 'HH', 6.36, 0.954, '', '' ], [ 20, 'AJUDANTE GERAL ', 8, 'HH', 6.36, 50.88, '', '' ], [ 125, 'CALDEREIRO', 8, 'HH', 13.05, 104.4, '', '' ], [ 0, 'ISOLADOR', 2, 'HH', 10.68, 21.36, '', '' ], [ 0, 'ISOLADOR', 8, 'HH', 10.68, 85.44, '', '' ], [ 0, 'ISOLADOR', 0.15, 'HH', 10.68, 1.6019999999999999, '', '' ], [ 585, 'PINTOR', 2, 'HH', 10.91, 21.82, '', '' ] ]
预期输出
[ [ 20, 'AJUDANTE GERAL ', 18.15, 'HH', 6.36, 115.434, '', '' ], [ 125, 'CALDEREIRO', 8, 'HH', 13.05, 104.4, '', '' ], [ 0, 'ISOLADOR', 10.15, 'HH', 10.68, 108.402, '', '' ], [ 585, 'PINTOR', 2, 'HH', 10.91, 21.82, '', '' ] ]
实现方案
实现思路:用reduce构建以岗位名为key的Map结构,遍历每行时如果key已存在就累加对应列,不存在就浅拷贝原行存入Map(避免修改原数组),最后把Map的value集合转为数组即可。
// sheetMapped 为原始输入数组 const uniqueRows = Array.from( sheetMapped.reduce((map, row) => { const jobName = row[1] if (map.has(jobName)) { // 已存在同岗位的行,累加对应列 const existRow = map.get(jobName) existRow[2] += row[2] existRow[5] += row[5] } else { // 不存在则浅拷贝原行存入,避免修改原数组 map.set(jobName, [...row]) } return map }, new Map()).values() )
该实现相比原双层循环方案有两个优势:
- 时间复杂度为O(n),仅需遍历一次原始数组,数据量大时性能优势明显
- 存入Map的是原行的浅拷贝,不会修改原始数组数据
内容的提问来源于stack exchange,提问作者T. Torquati
相关产品推荐
相关产品推荐

