js合并数组对象

樊小烦
  • 72

原始数据:

[
    {
        name:'张三',
        age:20,
    },
     {
        name:'张三',
        sex:'男',
    },
     {
        name:'李四',
        age:21,
    },
     {
        name:'李四',
        sex:'女',
    },
]

目标数据:

[
    {
        name:'张三',
        age:20,
        sex:'男'
    },
    {
        name:'李四',
        age:20,
        sex:'女'
    }
]
回复
阅读 1.2k
3 个回答
✓ 已被采纳

其实这种合并很简单的,

思路一,在对各种数据处理概念有的了解的情况下

先按 name 分组,会得到一个 { name => object[] } 结构的映射,再利用 Object.assign 对 object[] 对象进行合并,最好把这个映射表的所有值取出来,得到一个列表,就是需要的东西。

数据处理可以使用 Lodash 库

import _ from "lodash";

function merge(list) {
    return _(list).groupBy("name")
        .mapValues(group => Object.assign({}, ...group))
        .values()
        .value();
}

思路二,准备一个空的结果集,然后遍历数据源,对每一个源对象,在结果集中按 name 去寻找是否存在。若存在,将当前对象的属性合并进去 (Object.assign);若不存在,直接将当前对象加入结果集。

注意,由于 Object.assign 合并的时候会修改源对象,所以如果想保留源,新加入结果集时,应该加入对象的副本。可以通过展开运算符来实现。

function merge(list) {
    return list.reduce((r, it) => {
        const existed = r.find(({ name }) => it.name == name);
        if (existed) {
            Object.assign(existed, it);
        } else {
            r.push({...it});
        }
        return r;
    }, []);
}

这个处理中,按 name 在线性表中查找可能会花一些时间,尤其是这个表比较大的时候。这种情况下可以用映射表加速查找。也就是说,把结果集从一个列表(数组)变成一个映射表(对象)。这种做法其实就是分组的做法。只不过加上了合并逻辑,分组和合并同时进行了。

这个例子也可以用 reduce 来完成,但是考虑到题主可能对一些工具函数和新语法不太熟,这个示例代码写原始一点:

function merge(list) {
    const result = {};
    for (let i = 0; i < list.length; i++) {
        const it = list[i];
        const existed = result[it.name];
        if (existed) {
            Object.assign(existed, it);
        } else {
            result[it.name] = Object.assign({}, it);
        }
    }
    return Object.values(result);
}

它其实可以简化成

function merge(list) {
    return Object.values(
        list.reduce((r, it) => {
            Object.assign(r[it.name] ??= {}, it);
            return r;
        }, {})
    );
}

let newarr = arr.reduce(
pre,cur =>{
let index =pre.find(e=>e.name===cur.name)
if (index==-1) pre.push cur
else pre[index]=pre[index].concat(cur)
},[]
)

import GroupBy from 'lodash/groupBy'
const dataGroup = GroupBy(data, (item) => [item.name])
const resultData = [];
for (const key in dataGroup) {
  const options = {};
  dataGroup[key].map((item) => {
    // 将options和传进来的item合并
    Object.assign(options, item);
  })
  resultData.push(options);
}

image.png

宣传栏