如何高效获取两个数组的共有元素并去重(JS数组交集优化)
现有实现的效率问题
- 时间复杂度过高:原代码中
Array.includes、Array.indexOf都是O(n)级别的线性查找,两次嵌套filter遍历再加一次去重遍历,整体时间复杂度为O(n²),当数组长度较大时性能衰减非常明显 - 逻辑冗余:需求本质是求两个数组的交集(即同时存在于两个数组的元素)并去重,不需要对两个数组做双向过滤再合并,存在大量重复计算
- 额外内存开销:中间生成了
yFilteredByX、xFilteredByY、newArr三个临时数组,内存占用可以进一步压缩
优化方案
简洁高性能版(推荐,ES6+环境)
利用Set的特性:Set本身存储的元素天然唯一,且has方法的查找是O(1)复杂度,可以把整体时间复杂度降到O(m+n),代码量也大幅缩减:
const x = [1,3,7,4,9]; const y = [2,3,9,13,4]; // 先将其中一个数组转为Set,把查找开销从O(n)降为O(1) const xSet = new Set(x); // 过滤出交集元素后再转Set自动去重,最终转回数组即可 const uniqueArr = [...new Set(y.filter(item => xSet.has(item)))]; console.log(uniqueArr); // 输出 [3, 9, 4]
方案优势:
- 仅需两次线性遍历,性能远高于原实现,万级以上数据量下性能差距可达百倍
- 逻辑清晰,代码量仅为原实现的1/3
- 自动兼容单个数组内部存在重复元素的场景
兼容旧环境版(无ES6依赖)
如果运行环境不支持Set,可以用对象做哈希表实现相同的O(m+n)时间复杂度,过滤和去重一步完成:
const x = [1,3,7,4,9]; const y = [2,3,9,13,4]; const hash = {}; const uniqueArr = []; // 先将第一个数组的元素存入哈希表 for (let i = 0; i < x.length; i++) { hash[x[i]] = true; } // 遍历第二个数组,命中哈希表且未被加入结果的元素直接入组,同时标记避免重复 for (let i = 0; i < y.length; i++) { const item = y[i]; if (hash[item]) { uniqueArr.push(item); hash[item] = false; } } console.log(uniqueArr); // 输出 [3, 9, 4]
方案优势:
- 兼容所有JS运行环境,无语法兼容问题
- 全程仅生成一个结果数组,临时内存开销最低
- 无任何嵌套遍历,性能达到最优
补充说明
以上方案默认数组元素为原始值类型(数字、字符串、布尔值、null、undefined),如果数组元素是引用类型(对象、数组),只需要调整哈希存储的键为元素的唯一标识字段(比如业务id)即可,核心逻辑不变。
内容的提问来源于stack exchange,提问作者Ryan Froese
相关产品推荐
相关产品推荐

