如何高效对比两个数组对象找出差异项?

智慧(打工版) 阅读 9

我在做数据同步功能时,需要对比新旧两组用户数据,找出新增、删除和修改的项。但用双重循环性能太差,而且判断对象是否相等也不准确,试过 JSON.stringify 但顺序不同就失效了。

有没有更靠谱的方法?比如用 Map 或者第三方库?现在数据量一多页面就卡住,头疼。

const oldData = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }];
const newData = [{ id: 1, name: 'Alice Updated' }, { id: 3, name: 'Charlie' }];

// 想得到:updated: [id=1], added: [id=3], removed: [id=2]
我来解答 赞 1 收藏
二维码
手机扫码查看
1 条解答
UP主~广利
双重循环性能差是肯定的,O(n²) 复杂度数据量一大必卡。用 Map 是正解,把复杂度降到 O(n)。

思路很简单,用唯一标识(比如 id)建立 Map 索引,然后分别遍历对比就行。

直接上代码:

function diffData(oldData, newData, key = 'id') {
const oldMap = new Map(oldData.map(item => [item[key], item]));
const newMap = new Map(newData.map(item => [item[key], item]));

const added = [];
const removed = [];
const updated = [];

// 找新增和修改
newData.forEach(item => {
const oldItem = oldMap.get(item[key]);
if (!oldItem) {
added.push(item);
} else if (!isEqual(oldItem, item)) {
updated.push({ old: oldItem, new: item });
}
});

// 找删除
oldData.forEach(item => {
if (!newMap.has(item[key])) {
removed.push(item);
}
});

return { added, removed, updated };
}

// 简单的深度对比,不想引入库就用这个
function isEqual(a, b) {
return JSON.stringify(a) === JSON.stringify(b);
}

// 或者用更靠谱的方式,只对比需要的字段
function isEqual(a, b) {
const keysA = Object.keys(a);
const keysB = Object.keys(b);
if (keysA.length !== keysB.length) return false;
return keysA.every(key => a[key] === b[key]);
}


使用方式:

const oldData = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }];
const newData = [{ id: 1, name: 'Alice Updated' }, { id: 3, name: 'Charlie' }];

const result = diffData(oldData, newData);
// result.added: [{ id: 3, name: 'Charlie' }]
// result.removed: [{ id: 2, name: 'Bob' }]
// result.updated: [{ old: {id:1,name:'Alice'}, new: {id:1,name:'Alice Updated'} }]


关于对象对比,JSON.stringify 的问题你说得对,属性顺序不同就挂了。如果项目里已经用了 lodash,直接用 _.isEqual 做深度对比,比自己写的靠谱。或者干脆只对比业务关键字段,别全量对比。

如果数据量特别大(上万条),还可以考虑用 Web Worker 放到后台线程跑,避免阻塞主线程。不过大多数场景下 Map 方案够用了。
点赞 3
2026-03-01 19:02