登录
首页 >  文章 >  前端

Set高效处理数组并集交集差集方法

时间:2026-04-05 17:48:27 443浏览 收藏

本文深入解析了如何利用 JavaScript 的 Set 对象高效处理数组的并集、交集与差集运算,不仅提供了简洁实用的代码写法(如展开运算符结合 Set 去重实现并集、filter 配合 has() 实现交/差集),还重点揭示了实际开发中极易被忽视的关键细节:原始顺序是否保留、结果是否需要去重、基础类型与引用类型(如对象)的差异化处理策略(推荐提取 ID 或序列化而非直接使用 JSON.stringify),以及避免性能陷阱(如禁用 includes 而改用 Set.has() 实现 O(1) 查找)。对于中大型数据场景,这些看似微小的决策将显著影响运行效率与结果准确性。

如何用 Set 快速求出两个数组的并集、交集与差集

用 Set 实现数组并集:去重 + 合并

直接用 Set 构造器把两个数组展开合并,天然去重。注意:原始顺序不保留,且只适用于基础类型(如数字、字符串);引用类型(对象、数组)会被当作不同元素处理。

  • 写法:[...new Set([...arr1, ...arr2])]
  • 如果需保持 arr1 的顺序在前、arr2 中新元素补在后,改用:[...new Set(arr1), ...arr2.filter(x => !arr1.includes(x))]
  • 性能提示:对大数组慎用 includes,它 O(n) 查找;可先转 new Set(arr1) 再用 has(),提升到 O(1)

用 Set 求交集:filter + has 是关键

交集本质是“在 A 里,且也在 B 里”。把其中一个数组转成 Set,再用 filter 配合 has() 判断,比嵌套循环快得多。

  • 标准写法:arr1.filter(x => setB.has(x)),其中 setB = new Set(arr2)
  • 注意重复项:如果 arr1 有重复,结果也会保留这些重复 —— Set 只用于查找,不自动去重结果
  • 若要结果无重复,包一层:[...new Set(arr1.filter(x => setB.has(x)))]
  • 错误示范:arr1.filter(x => arr2.includes(x)) —— 对万级数组可能卡顿,includes 是线性扫描

用 Set 做差集(A - B):别漏掉去重逻辑

差集即“A 中有、B 中没有”的元素。和交集类似,但逻辑取反。容易忽略的是:A 自身若有重复,是否要保留?多数场景要的是“唯一差集”,所以通常需要最终去重。

  • 基础差集(保留 A 原重复):arr1.filter(x => !setB.has(x))
  • 去重差集(推荐):[...new Set(arr1.filter(x => !setB.has(x)))]
  • 反向差集(B - A)只需调换变量:[...new Set(arr2.filter(x => !setA.has(x)))]
  • 陷阱:Set 不能直接减,setA - setB 是 NaN —— JavaScript 没有集合运算符,必须靠数组方法桥接

复杂类型(对象/数组)怎么处理?Set 失效了

Set 判等用的是 Object.is(),所以两个结构相同但内存地址不同的对象,在 Set 里就是不同元素。这时不能直接用 new Set(arr),得降维。

  • 简单方案:用 JSON 字符串化键名(仅限可序列化、无函数/undefined/循环引用的数据):new Set(arr.map(x => JSON.stringify(x)))
  • 更稳方案:提取唯一标识字段(如 id),构造 Set 存 ID,再做 filterconst idsB = new Set(arr2.map(x => x.id)); arr1.filter(x => !idsB.has(x.id))
  • 千万别用 arr1.filter(x => !arr2.find(y => _.isEqual(x, y)))(依赖 Lodash)—— 每次都全量遍历,O(n²),大数据量明显卡

实际用的时候,最常被绕过的其实是“要不要去重结果”和“原始顺序是否重要”这两个判断点。Set 本身不维护插入顺序以外的语义,所有操作都要主动想清楚这两层。

理论要掌握,实操不能落!以上关于《Set高效处理数组并集交集差集方法》的详细介绍,大家都掌握了吧!如果想要继续提升自己的能力,那么就来关注golang学习网公众号吧!

资料下载
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>