JavaScript:合并同一数组内多对象并重构数据结构
嘿,这个需求其实挺常见的,用JavaScript的数组方法就能轻松实现,给你几个实用的方案:
解决方案
方法一:map + reduce(简洁优雅)
这是最常用的写法,利用数组的高阶方法快速完成合并求和:
var data = [ [{ jan: 10, feb: 20, mar: 30, type: "one" }, { jan: 20, feb: 10, mar: 40, type: "one" }], [ { jan: 10, feb: 20, mar: 30, type: "two" }, { jan: 20, feb: 10, mar: 40, type: "two" }] ]; const mergedData = data.map(group => { return group.reduce((acc, curr) => { // 累加月份字段的值 acc.jan += curr.jan; acc.feb += curr.feb; acc.mar += curr.mar; // 保留type(同组内type一致,随便取哪个都没问题) acc.type = curr.type; return acc; }, { jan: 0, feb: 0, mar: 0, type: '' }); // 初始化累加对象 }); console.log(mergedData);
代码解释:
- 外层
map遍历原数组的每个子数组(也就是同一type的对象分组) - 每个子数组用
reduce做累加:初始值是一个预设好结构的空对象,字段初始值为0 - 每次迭代时,把当前对象的月份字段值加到累加对象的对应字段上,同时同步
type字段 - 最终
map会把每个分组的合并结果收集成新数组,就是你要的结构
方法二:嵌套循环(直观易懂)
如果刚接触JavaScript,觉得高阶方法有点绕,可以用更直观的嵌套循环实现:
var data = [ [{ jan: 10, feb: 20, mar: 30, type: "one" }, { jan: 20, feb: 10, mar: 40, type: "one" }], [ { jan: 10, feb: 20, mar: 30, type: "two" }, { jan: 20, feb: 10, mar: 40, type: "two" }] ]; const mergedData = []; // 遍历每个分组 for (const group of data) { // 初始化合并对象,用分组第一个元素的type const mergedItem = { jan: 0, feb: 0, mar: 0, type: group[0].type }; // 遍历分组里的每个对象,累加字段值 for (const item of group) { mergedItem.jan += item.jan; mergedItem.feb += item.feb; mergedItem.mar += item.mar; } // 把合并好的对象加入结果数组 mergedData.push(mergedItem); } console.log(mergedData);
代码解释:
- 先创建空数组存储最终结果
- 外层循环遍历每个
type的分组,先初始化一个合并对象,预设字段初始值为0,type直接取分组第一个元素的(因为同组type都一样) - 内层循环遍历分组里的每个对象,把月份字段的值逐个累加到合并对象里
- 最后把合并好的对象推入结果数组即可
进阶优化:动态处理字段(适配未来扩展)
如果以后要加新的月份字段(比如apr、may),不想每次手动修改代码,可以用动态遍历的方式:
var data = [ [{ jan: 10, feb: 20, mar: 30, type: "one" }, { jan: 20, feb: 10, mar: 40, type: "one" }], [ { jan: 10, feb: 20, mar: 30, type: "two" }, { jan: 20, feb: 10, mar: 40, type: "two" }] ]; const mergedData = data.map(group => { return group.reduce((acc, curr) => { // 遍历当前对象的所有键 for (const key in curr) { if (key === 'type') { // type字段直接赋值 acc[key] = curr[key]; } else { // 数字字段自动累加,兼容新增字段 acc[key] = (acc[key] || 0) + curr[key]; } } return acc; }, {}); // 初始化为空对象,动态生成字段 }); console.log(mergedData);
这种写法不管以后加多少数字类型的字段,都不需要修改累加逻辑,灵活性更高。
内容的提问来源于stack exchange,提问作者kcNeko
相关产品推荐
相关产品推荐

