
本文介绍一种高效、可复用的方法,通过 set 快速索引旧数组中的 id,结合 map 构建新结果数组:对存在于旧数组的项保留原有 active 状态,对新出现的项自动设为 false。
本文介绍一种高效、可复用的方法,通过 set 快速索引旧数组中的 id,结合 map 构建新结果数组:对存在于旧数组的项保留原有 active 状态,对新出现的项自动设为 false。
在前端开发中,常需根据新数据源动态更新已有对象列表的状态(如菜单项、配置项或表单项),而新旧数据结构高度相似但嵌套层级不同——例如旧数组每个元素是 { item: { id, path }, active: boolean },新数组则是扁平的 [ { id, path } ]。此时,核心诉求不是简单深比较,而是按 id 做增量同步:保留匹配项的原始 active 值,为新增项赋予默认状态(如 false)。
以下是一个简洁、高性能的实现方案:
const oldItems = [
{ item: { id: '1', path: "some text" }, active: true },
{ item: { id: '2', path: "some text" }, active: true },
{ item: { id: '4', path: "some text" }, active: false },
{ item: { id: '10', path: "some text" }, active: false }
];
const newItems = [
{ id: '1', path: "some text" },
{ id: '4', path: "some text" },
{ id: '6', path: "some text" }
];
// 步骤 1:提取所有旧项 ID,构建 O(1) 查询集合
const oldIds = new Set(oldItems.map(obj => obj.item.id));
// 步骤 2:遍历新数组,按 ID 判断是否“已存在”,决定 active 值
const result = newItems.map(item => ({
item,
active: oldIds.has(item.id)
}));
console.log(result);
// 输出:
// [
// { item: { id: '1', path: "some text" }, active: true },
// { item: { id: '4', path: "some text" }, active: false },
// { item: { id: '6', path: "some text" }, active: false }
// ]
✅ 关键优势说明:
- 时间复杂度最优:Set.has() 为 O(1),整体为 O(n + m),远优于嵌套循环的 O(n×m);
- 语义清晰:oldIds.has(item.id) 直观表达“该 ID 是否在历史状态中存在”;
- 默认安全:未匹配项自动获得 active: false,符合业务约定,无需额外判断;
- 无副作用:纯函数式写法,不修改原数组,便于测试与状态管理。
⚠️ 注意事项:
- 确保 id 字段类型一致(如均为字符串),避免 '1' === 1 类型误判;
- 若需支持深层属性匹配(如 item.meta.version),应提前规范化数据结构;
- 如需保留旧数组中未出现在新数组里的项(即做“差集+交集+并集”混合操作),本方案需扩展为先 filter 再 concat,此处聚焦“以新数组为准”的典型场景。
该模式可轻松封装为通用工具函数,适配各类 ID 驱动的状态同步需求。










