如何对比两个对象数组并提取属性发生变更的对象元素
问题原因
你现有的实现存在两个核心问题导致调整元素位置时会误判:
- 直接用
JSON.stringify序列化对象做对比:如果两个对象属性顺序不一致,哪怕所有属性值完全相等,序列化结果也会不同,会被误判为变更 - 没有以
id作为唯一标识符匹配新旧数组的同一条数据:只是全局匹配序列化后的字符串,无法正确定位到两条原本是同一条的数据做属性对比
解决方案
核心思路是先用id作为唯一键把旧数组转成查找表,再逐一对新数组元素匹配同id的旧元素,全属性对比是否有变更:
// 把旧数组转成 id 为 key 的 Map,提升查找效率 const oldMap = new Map(a.map(item => [item.id, item])) const result = b.filter(newItem => { // 找到同id的旧数据 const oldItem = oldMap.get(newItem.id) // 旧数据不存在说明是新增,属于变更 if (!oldItem) return true // 拿到两个对象的所有属性key,去重后遍历对比 const allKeys = new Set([...Object.keys(oldItem), ...Object.keys(newItem)]) // 只要有一个属性值不相等就判定为变更 for (const key of allKeys) { if (oldItem[key] !== newItem[key]) { return true } } // 所有属性都相等,不属于变更 return false })
验证效果
这个实现不受数组元素顺序、对象属性顺序影响,且适配任意非嵌套的对象属性,你给出的测试用例运行后会得到正确输出:
[ { "id": "132a5f3b-7350-44e6-8ac8-3ba1b558ff1c", "name": "acoo", "price": "25" }, { "id": "b1cf9e9d-e712-4624-b754-fb9c48a75716", "name": "Yhgg", "price": "26" }, { "id": "01381e2c-ee25-4461-93cb-d54c812551e9", "name": "anixx", "price": "25" } ]
内容的提问来源于stack exchange,提问作者SHARAN SUTRAPU
相关产品推荐
相关产品推荐

