如何基于属性匹配合并对象数组?求ES6/ES7简洁方案
解决方案:基于ID更新数组对象的selected属性
我来帮你搞定这个问题!你现在的核心问题是嵌套使用了两次map,导致每个baseID元素都生成了一个对应selectedID长度的数组,最终得到了不符合预期的嵌套结构。我们可以换个更高效简洁的思路——先构建一个快速查找的映射表,再遍历baseID来更新属性。
问题分析
你原来的代码里,baseID.map内部又套了一层selectedID.map,这意味着baseID里的每一个对象,都会被转换成一个包含selectedID长度元素的数组,自然就出现了嵌套结构,这和你想要的扁平化结果完全不符。
优化方案(ES6+)
我们可以先把selectedID转换成以id为键的映射表,这样后续查找对应selected状态的时间复杂度是O(1),再遍历baseID完成属性更新即可:
步骤1:构建ID与selected状态的映射表
用Map来存储ID和对应的选中状态(推荐,因为ID可以是任意类型):
const selectedMap = new Map(selectedID.map(item => [item.id, item.selected]));
如果你的ID都是字符串/数字,也可以用普通对象实现:
const selectedObj = Object.fromEntries(selectedID.map(item => [item.id, item.selected]));
步骤2:遍历baseID更新selected值
用扩展运算符...复制原对象,再覆盖selected属性——如果映射表里有对应ID的状态就用它,没有就保留原对象的selected值:
const result = baseID.map(item => ({ ...item, selected: selectedMap.get(item.id) ?? item.selected }));
完整代码示例
let selectedID = [ { "id": 7, "selected": true }, { "id": 1, "selected": true } ]; let baseID = [ { "id": 7, "selected": false }, { "id": 12, "selected": false }, { "id": 13, "selected": false }, { "id": 1, "selected": false }, { "id": 9, "selected": false }, { "id": 10, "selected": false } ]; const selectedMap = new Map(selectedID.map(item => [item.id, item.selected])); const op = baseID.map(item => ({ ...item, selected: selectedMap.get(item.id) ?? item.selected })); console.log(op);
预期输出
[ { "id": 7, "selected": true }, { "id": 12, "selected": false }, { "id": 13, "selected": false }, { "id": 1, "selected": true }, { "id": 9, "selected": false }, { "id": 10, "selected": false } ]
方案优势
- 性能更优:构建映射表是O(n),遍历
baseID是O(m),总时间复杂度O(n+m),比你原来的嵌套map(O(n*m))高效得多,数据量大时差异明显。 - 代码简洁:用ES6扩展运算符和ES2020的空值合并运算符
??,逻辑清晰易懂。??比||更安全,只会在值为null或undefined时返回默认值,避免误判0、空字符串等假值。 - 结构正确:只用一次
map就得到扁平化的目标数组,完全符合预期。
内容的提问来源于stack exchange,提问作者xkeshav
相关产品推荐
相关产品推荐

