如何基于两个条件对对象数组执行reduce合并计算?
对象数组合并问题求助
我需要基于choosenNum和game两个字段合并对象数组,将相同字段组合的对象的count求和,替换原count值。
原始数组
const gamesAndChoosenNumbers = [ { choosenNum: '15', count: 10, game: 'AB', gameCode: 'double', }, { choosenNum: '15', count: 5, game: 'AB', gameCode: 'double', }, { choosenNum: '16', count: 20, game: 'AB', gameCode: 'double', }, { choosenNum: '16', count: 20, game: 'AB', gameCode: 'double', }, { choosenNum: '16', count: 10, game: 'AB', gameCode: 'double', }, { choosenNum: '150', count: 10, game: 'SUPER', gameCode: 'super', }, { choosenNum: '150', count: 10, game: 'SUPER', gameCode: 'super', }, { choosenNum: '155', count: 20, game: 'SUPER', gameCode: 'super', }, { choosenNum: '155', count: 20, game: 'SUPER', gameCode: 'super', }, { choosenNum: '200', count: 10, game: 'BOX', gameCode: 'box', }, { choosenNum: '200', count: 10, game: 'BOX', gameCode: 'box', }, { choosenNum: '155', count: 20, game: 'BOX', gameCode: 'box', }, ];
期望结果
const mergedGamesAndChoosenNumbers = [ { choosenNum: '15', count: 15, game: 'AB', gameCode: 'double', }, { choosenNum: '16', count: 50, game: 'AB', gameCode: 'double', }, { choosenNum: '150', count: 20, game: 'SUPER', gameCode: 'super', }, { choosenNum: '155', count: 40, game: 'SUPER', gameCode: 'super', }, { choosenNum: '200', count: 20, game: 'BOX', gameCode: 'box', }, { choosenNum: '155', count: 20, game: 'BOX', gameCode: 'box', }, ];
尝试的代码(未解决问题)
const duplicateElementa = gamesAndChoosenNumbers.reduce((x, y, i) => { console.log({ i, x, y }); if (x.map((it) => it.choosenNum).includes(y.choosenNum)) { console.log({ i1: i, x1: x[i - 1], y1: y }); if (x[i - 1].game === y.game) { return [...x, { ...y, count: x[i - 1]?.count + y.count }]; } } else { return [...x, y]; } }, []); const nondupes = gamesAndChoosenNumbers.filter( (it) => !dupeNums.includes(it.choosenNum), ); const dupesMerged = duplicateElementa.map((it, i, arr) => { const gt = arr.sort((a, b) => b.count - a.count); const st = gt.reduce((x, y, i, carr) => { if ( x.map((it) => it.choosenNum).includes(y.choosenNum) && x.map((it) => it.game).includes(y.game) ) { return x; } else { return [...x, y]; } }, []); return st; })[0]; const final: [] = dupesMerged .filter((it) => { console.log(nondupes.map((u) => u.choosenNum).includes(it.choosenNum)); if (!nondupes.map((u) => u.choosenNum).includes(it.choosenNum)) { return it; } }) .concat(nondupes);
问题出在当choosenNum为155出现在不同game分组时,合并逻辑错误,无法正确区分不同game下的同一choosenNum。
解决方案
核心思路是用reduce构建一个以choosenNum + game为键的对象,累计求和count,最后将对象的值转为数组即可:
const merged = Object.values(gamesAndChoosenNumbers.reduce((acc, curr) => { // 用choosenNum和game拼接成唯一键,区分不同分组 const key = `${curr.choosenNum}-${curr.game}`; if (acc[key]) { // 已存在分组则累加count acc[key].count += curr.count; } else { // 不存在则复制当前对象存入累加器 acc[key] = { ...curr }; } return acc; }, {})); console.log(merged);
代码说明
- 用
choosenNum和game拼接成唯一标识的键,确保同一choosenNum在不同game下被视为独立分组 - 遍历数组时,若键已存在则累加
count,否则将当前对象存入累加器 - 最后用
Object.values()将累加器对象转为数组,直接得到合并后的结果
这个方案逻辑简洁,时间复杂度为O(n),能正确处理所有分组场景,包括同一choosenNum对应不同game的情况。
内容的提问来源于stack exchange,提问作者Ali-D-Coded
相关产品推荐
相关产品推荐

