如何合并多个结构相似的对象数组并按用户汇总积分?
问题描述
API返回的response.survey是一个包含多个对象的数组,每个对象内是带数字键的用户数据,示例结构如下:
const response = { survey: [ { 1: { id: 1, user: 'user_1', points: 5 }, 2: { id: 2, user: 'user_2', points: 3 } // ...更多用户数据 }, { 1: { id: 1, user: 'user_1', points: 10 }, 2: { id: 2, user: 'user_2', points: 0 } // ...更多用户数据 } // ...更多这样的对象 ] };
需要将这些数据合并为按用户分组、累加积分的结构:
[ { user: 'user_1', points: 15 }, { user: 'user_2', points: 3 } // ...其他用户 ]
当前获取到2组各25个数据点,但合并后得到52个结果,不符合预期。尝试的代码如下:
let newArr = []; response.survey.map((ballot, i) => { for (const key in ballot) { if (newArr.length == 0) { let newObj = { name: pos[key].user, points: pos[key].points } newArr.push(newObj); } else { for (let k = 0; k < newArr.length; k++) { if (newArr[k].name === pos[key].name) { newArr[k].points += pos[key].points; } else { if (k + 1 == newArr.length) { let newObj = { name: pos[key].name, points: pos[key].points } newArr.push(newObj); } } } } } });
解决方案
你的代码核心问题是:遍历newArr时,只要当前元素与用户不匹配,就会在遍历到最后一个元素时重复添加新对象,导致同一用户被多次存入数组。
用对象映射表可以高效解决这个问题,以用户名作为唯一键来累加积分,逻辑清晰且避免重复:
// 初始化映射表,按用户名存储累计积分 const userPointsMap = {}; // 遍历所有投票数据 response.survey.forEach(ballot => { // 提取当前投票里的所有用户数据,无需遍历数字键 Object.values(ballot).forEach(({ user, points }) => { // 累加积分:用户存在则加,不存在则初始化 userPointsMap[user] = (userPointsMap[user] || 0) + points; }); }); // 将映射表转换为目标数组格式 const mergedResult = Object.entries(userPointsMap).map(([user, points]) => ({ user, points })); console.log(mergedResult);
关键说明
Object.values(ballot):直接提取每个投票对象内的所有用户数据,跳过数字键的遍历,代码更简洁。- 映射表
userPointsMap:确保每个用户名只会对应一条记录,彻底避免重复统计。 - 时间复杂度为O(n),n是所有用户数据的总数量,处理数百条数据毫无压力。
内容的提问来源于stack exchange,提问作者jffy
相关产品推荐
相关产品推荐

