如何用ES6/ES7一行代码合并数组与对象数组并保留指定顺序?
当然可以用ES6/ES7的语法一行搞定这个需求!咱们先理清楚你的核心目标:先按arr1的id顺序匹配arr2里的对象,再把arr2中没出现在arr1里的对象追加到末尾。先分析下你之前的错误写法,再给出正确实现:
需求回顾
合并数值数组
arr1与对象数组arr2,先按arr1的id顺序排列对应对象,再将arr2中arr1未包含的id对应的对象追加到末尾,用ES6/ES7语法一行完成。
错误实现问题分析
错误实现1
const arr3 = []; arr3 = arr1.map(x => ([...arr1, arr2]));
这个写法完全没做id匹配的逻辑——每次map迭代都把整个arr1和arr2拼成新数组塞进去,最后得到的是嵌套了原数组的结构,自然和预期结果相差甚远。
错误实现2
const arr3 = []; arr3 = arr1.map(id => arr3.push(arr2.id === id));
这里的问题有两个:一是arr2是数组,直接访问arr2.id根本不存在;二是push返回的是数组的新长度,同时你在map里修改arr3本身,逻辑完全混乱,所以最终得到的全是false。
正确的一行实现
基础版(代码简洁,适合中小数据量)
const arr3 = [...arr1.map(id => arr2.find(item => item.id === id)), ...arr2.filter(item => !arr1.includes(item.id))];
逻辑拆解:
arr1.map(id => arr2.find(item => item.id === id)):遍历arr1的每个id,从arr2中找到对应id的对象,这部分就实现了按arr1顺序排列的目标。arr2.filter(item => !arr1.includes(item.id)):过滤出arr2中id不在arr1里的对象,也就是需要追加到末尾的部分。- 用扩展运算符
...把这两部分合并成一个新数组,正好符合你的期望输出。
性能优化版(适合大数据量)
如果arr2的数据量很大,find的循环查找会影响性能,咱们可以先把arr2转成Map来快速查找,同样一行搞定:
const arr3 = (objMap => [...arr1.map(id => objMap.get(id)), ...arr2.filter(item => !arr1.includes(item.id))])(new Map(arr2.map(item => [item.id, item])));
逻辑拆解:
- 先通过
new Map(arr2.map(item => [item.id, item]))创建一个以id为键、对应对象为值的Map,这样后续objMap.get(id)能直接定位到对象,比find的循环查找效率高很多。 - 后面的逻辑和基础版一致,合并按顺序匹配的对象和剩余对象。
验证结果
用你的测试数据运行上面的代码,就能得到你期望的输出:
const arr3 = [ {id: 7, type: "Label", name: "This is a crazy new one"}, {id: 1, type: "Text", name: "Test Text Property"}, {id: 2, type: "Text", name: "Test Create Property"}, {id: 5, type: "MultiChoiceMultiAnswer", name: "test"}, {id: 8, type: "MultiChoiceMultiAnswer", name: "Another Test Property"}, {id: 10, type: "Label", name: "New Label"}, {id: 9, type: "Text", name: "New Text"} ];
内容的提问来源于stack exchange,提问作者proph3t
相关产品推荐
相关产品推荐

