JavaScript中对比两个对象数组,如何获取变更行索引与属性?
对比动态对象数组获取变更行及属性的解决方案
问题场景
我从API获取两个动态对象数组(字段由终端用户创建,预先未知键名),一个为原数组,另一个是修改后的版本。需要对比这两个数组,获取修改后数组中变更的rowIndex以及具体变更的对象属性。现有代码只能获取到对象本身,无法得到changedKeys,期望输出如下格式的结果:
[ { "rowIndex": 1, "changedKeys": ["model"] }, { "rowIndex": 3, "changedKeys": ["brand", "model"] } ]
原代码示例
const originalData = [{ brand: 'Honda', model: 'Accord' }, { brand: 'Honda', model: 'Civic' }, { brand: 'Toyota', model: 'Camry' }, { brand: 'Toyota', model: 'Corolla' }] const data = [{ brand: 'Honda', model: 'Accord' }, { brand: 'Honda', model: 'CRV' }, { brand: 'Toyota', model: 'Camry' }, { brand: 'Nissan', model: 'RAV4' }] console.log(data.reduce((a, c, i, arr) => { if (!originalData.some(j => { return _.isEqual(c, j) })) { a.push({ rowIndex: i, changedKeys: arr[i] }) } return a }, []))
解决方案代码
const originalData = [{ brand: 'Honda', model: 'Accord' }, { brand: 'Honda', model: 'Civic' }, { brand: 'Toyota', model: 'Camry' }, { brand: 'Toyota', model: 'Corolla' }] const data = [{ brand: 'Honda', model: 'Accord' }, { brand: 'Honda', model: 'CRV' }, { brand: 'Toyota', model: 'Camry' }, { brand: 'Nissan', model: 'RAV4' }] const changes = data.reduce((acc, currentObj, index) => { const originalObj = originalData[index]; // 原数组无对应行时,直接收集当前对象所有键 if (!originalObj) { acc.push({ rowIndex: index, changedKeys: Object.keys(currentObj) }); return acc; } // 合并两个对象的所有键,避免遗漏新增/删除的属性 const allKeys = new Set([...Object.keys(originalObj), ...Object.keys(currentObj)]); const changedKeys = []; // 遍历所有键,对比值是否变更 for (const key of allKeys) { if (!_.isEqual(originalObj[key], currentObj[key])) { changedKeys.push(key); } } // 存在变更时才加入结果 if (changedKeys.length > 0) { acc.push({ rowIndex: index, changedKeys }); } return acc; }, []); console.log(changes);
代码说明
- 同索引行对比:默认数组行顺序不变,直接取原数组对应索引的对象进行对比(若业务中存在行排序变化,需先通过唯一标识匹配对应行再对比)。
- 全键覆盖:用
Set合并原对象与当前对象的所有键,确保不会遗漏新增或删除的属性。 - 深度值对比:借助
_.isEqual实现深度对比,支持嵌套对象等复杂类型的变更判断。 - 结果过滤:仅收集存在属性变更的行,避免无意义的空数据。
运行后输出与期望格式完全一致。
内容的提问来源于stack exchange,提问作者arunmmanoharan
相关产品推荐
相关产品推荐

