JS中Set无内置差集和对称差集方法,需手动实现:差集用[...a].filter(x => !b.has(x)),对称差集为差集并集或双遍历add,可封装为复用函数。

JS 的 Set 本身不提供直接的差集(A − B)或对称差集(A △ B)方法,但可以用简洁、高效的方式手动实现,核心思路是遍历 + 条件过滤。
差集(A − B):只保留在 A 中但不在 B 中的元素
遍历集合 A,用 B.has() 判断每个元素是否**不属于** B,符合条件的加入新 Set。
示例代码:
const a = new Set([1, 2, 3, 4]);
const b = new Set([3, 4, 5, 6]);
<p>const difference = new Set([...a].filter(x => !b.has(x)));
// → Set { 1, 2 }
</p>
说明:
• 展开 a 为数组是为了使用 filter;
• 不建议用 for...of 手动循环再 add,filter 更声明式、简洁;
• 时间复杂度 O(n),因为 Set.prototype.has() 是平均 O(1)。
对称差集(A △ B):在 A 或 B 中,但不同时在两者中的元素
等价于 (A − B) ∪ (B − A)。可一次遍历合并两个方向的筛选结果。
推荐写法(单次遍历 + 两次判断):
const a = new Set([1, 2, 3]);
const b = new Set([2, 3, 4, 5]);
<p>const symmetricDifference = new Set([
...[...a].filter(x => !b.has(x)),
...[...b].filter(x => !a.has(x))
]);
// → Set { 1, 4, 5 }
</p>
优化提示:
• 若数据量大,可避免重复展开,改用 forEach 分别 add:
const result = new Set();<br> a.forEach(x => !b.has(x) && result.add(x));<br> b.forEach(x => !a.has(x) && result.add(x));
• 这种方式只遍历两次、不生成中间数组,内存更友好。
封装成可复用的工具函数
把逻辑抽离,提升可读性和复用性:
const setDifference = (a, b) => new Set([...a].filter(x => !b.has(x)));
const setSymmetricDifference = (a, b) =>
new Set([
...setDifference(a, b),
...setDifference(b, a)
]);
<p>// 使用
const A = new Set(['a', 'b', 'c']);
const B = new Set(['b', 'c', 'd']);
console.log(setDifference(A, B)); // Set {'a'}
console.log(setSymmetricDifference(A, B)); // Set {'a', 'd'}
</p>
注意:
• 函数接收任意可迭代对象(如数组、Set),但内部会转为 Set 处理更安全;
• 若需强类型保障,可在入参处用 new Set(iterable) 统一标准化。
不适用 Array.from?为什么用 [...set]?
[...set] 和 Array.from(set) 效果一致,都转为数组。前者更短、更常用;后者在需要映射或带 thisArg 时更灵活。日常差集计算中,扩展运算符足够清晰直接。











