数组交集并集差集

实现两个数组的交集、并集、差集运算

问题

给定两个数组,实现它们的交集、并集、差集运算。

解答

使用 Set 实现

const arr1 = [1, 2, 3, 4, 5];
const arr2 = [3, 4, 5, 6, 7];

// 交集:两个数组都有的元素
function intersection(a, b) {
  const setB = new Set(b);
  return [...new Set(a)].filter(x => setB.has(x));
}

// 并集:两个数组所有元素(去重)
function union(a, b) {
  return [...new Set([...a, ...b])];
}

// 差集:在 a 中但不在 b 中的元素
function difference(a, b) {
  const setB = new Set(b);
  return [...new Set(a)].filter(x => !setB.has(x));
}

console.log(intersection(arr1, arr2)); // [3, 4, 5]
console.log(union(arr1, arr2));        // [1, 2, 3, 4, 5, 6, 7]
console.log(difference(arr1, arr2));   // [1, 2]

对称差集

// 对称差集:只在其中一个数组中出现的元素
function symmetricDifference(a, b) {
  const setA = new Set(a);
  const setB = new Set(b);
  return [
    ...a.filter(x => !setB.has(x)),
    ...b.filter(x => !setA.has(x))
  ];
}

console.log(symmetricDifference(arr1, arr2)); // [1, 2, 6, 7]

处理对象数组

const users1 = [{ id: 1 }, { id: 2 }, { id: 3 }];
const users2 = [{ id: 2 }, { id: 3 }, { id: 4 }];

// 通过指定 key 比较
function intersectionBy(a, b, key) {
  const keys = new Set(b.map(item => item[key]));
  return a.filter(item => keys.has(item[key]));
}

function differenceBy(a, b, key) {
  const keys = new Set(b.map(item => item[key]));
  return a.filter(item => !keys.has(item[key]));
}

console.log(intersectionBy(users1, users2, 'id')); // [{ id: 2 }, { id: 3 }]
console.log(differenceBy(users1, users2, 'id'));   // [{ id: 1 }]

自定义比较函数

// 更灵活的实现,支持自定义比较逻辑
function intersectionWith(a, b, comparator) {
  return a.filter(x => b.some(y => comparator(x, y)));
}

function differenceWith(a, b, comparator) {
  return a.filter(x => !b.some(y => comparator(x, y)));
}

const result = intersectionWith(users1, users2, (a, b) => a.id === b.id);
console.log(result); // [{ id: 2 }, { id: 3 }]

关键点

  • Set 的 has() 方法时间复杂度为 O(1),比数组的 includes() 更高效
  • 先将数组转为 Set 可以自动去重
  • 差集不满足交换律:A - B ≠ B - A
  • 对象数组需要指定比较的 key 或自定义比较函数
  • 大数据量时优先使用 Set,避免嵌套循环