# 在js中合并两个数组中key值相同的项 ## 前言 风和日丽的一天,群里突然抛出一个问题,现在有一个数组,其中有多个项的key属性是一样的,现在需要进行合并 示例代码结构 ```js // 输入的数据 const arr = [ {key: 1, a: 'a'}, {key: 1, b: 'b'}, {key: 2, a: 'a'}, {key: 2, b: 'b', c: 'c'}, {key: 3, a: 'a', b: 'b'}, {key: 4, a: 'a', b: 'b'}, ] ``` 需要的结果 ```js // 需要的结果 const arr_res = [ {key: 1, a: 'a', b: 'b'}, {key: 2, a: 'a', b: 'b', c: 'c'}, {key: 3, a: 'a', b: 'b'}, {key: 4, a: 'a', b: 'b'}, ] ``` ## 解决方案 > [!tip] > 记录了大佬们的回答,都是用的上面的数据以及变量,测试下方代码需要连同上方代码一起复制 ### 使用reduce进行处理 #### **罗老师版本** 这个版本为湿鸡老师所写 ```js var obj = arr.reduce((_,o)=>{ _[o.key] ? (_[o.key] = Object.assign(_[o.key],o)) : (_[o.key] = o);return _; },{}) var a = []; for( var key in obj ){ a.push(obj[key]) } console.log(a); ``` 用reduce循环将key作为累加值的键,用`Object.assign`来处理key值相同的项. 最后使用数组转换为 #### **群宠晨晨大佬的一行版本** 这个版本,为大佬所写,过于高端.和湿鸡老师写的有所不同,虽然同样是使用`reduce`,但是我特么一下真的看不懂. 但是大佬有另一个版本 ```js arr.reduce((r, o) => ((r[o.key] = {...r[o.key], ...o}), r), []).filter(i => i) ``` 在这个版本大佬看见数据结构的key值是用数字组成的,可以转换为数组下标 #### **晨晨大佬的一行版本扩写** ```js // 晨晨大佬一行版本修改 let x2 = arr.reduce((r,o)=>{ // 通过解构进行合并不同的项 r[o.key] = {...r[o.key], ...o} return r },[]) // 因为key值不是百分百都对应数组的下标.所以用filter过滤 x2 = x2.filter(i=>i) console.log(x2); ``` ### 其他方式处理 > [!tip] > 其他的解决方法 #### **晨晨大佬的mapFor版本** ```js const map = new Map() let crt for (const item of arr) { crt = map.get(item.key) map.set(item.key, {...crt, ...item}) } const res = [...map.values()] ``` 使用map来替代对象,对象不好转化为数组,map的values函数可以返回所有的值 ## 知识点总结 ### 1. `reduce`的使用,[MDN详细文档](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce) 在js里,为array进行了部分扩展,`reduce`函数将会将数组中的每个元素执行你所提供的reduce回调函数,返回指定值 > [!tip] > 这个函数中callback函数接收的参数和其他的数组函数基本一致,除了第一个参数有所不同,后续参数基本一致 1. 参数解释 - `callback`要执行的函数 - `initValue`初始值 ```js // @param {Function} callback 要执行的函数 // @param {*} initValue 初始值.可选默认为 undefined Array.reduce(callback,initValue) ``` 2. callback函数可以接收的参数 - `accumulator`累加器,上次循环的返回值,如果是第一次循环,则值为`initValue`. - `currentValue`当前值,当前循环到的数组元素的实际值 - `index `下标,当前循环到的数组元素的下标值 - `array`原始数组,当前循环的原始数组 > [!tip] > 一个偏向于官方风格的示例,用来求数组中的和 执行下方代码 ```js let result = [0,1,2,3].reduce((accumulator,currentValue,index,array)=>{ console.log(`accumulator:${accumulator}\ncurrentValue:${currentValue}\nindex:${index}\n`) return accumulator + currentValue },-1) console.log(`最后返回的值${result}`) ``` 控制台输出 ``` accumulator:-1 currentValue:0 index:0 accumulator:-1 currentValue:1 index:1 accumulator:0 currentValue:2 index:2 accumulator:2 currentValue:3 index:3 最后返回的值5 ``` ### 2. `js`解构赋值 ### 3. `Map`的使用