javascript数组交集、并集、差集详解

197 阅读2分钟

交集

目前网上有很多求javascript数组交集的方式,其中最常用的便是以下实现:

const intersection = (arr1, arr2) => arr1.filter(item => arr2.includes(item))

大部分实现都是基于上述实现进行的变化。但上述实现存在一个巨大的问题,即处理有重复元素的数组的交集会出现问题,因此接下来这篇文章将着重探讨处理有重复元素的数组的交集。

Array<number>

首先,我们从元素为数字的数组入手,实现如下:

function intersection (arr1, arr2) {
  // sort方法属于数组的可变方法,会导致原数组发生变化,因此做一次浅拷贝
  const sortArr1 = [...arr1].sort((a, b) => a-b)
  const sortArr2 = [...arr2].sort((a, b) => a-b)
  const { length: length1 } = sortArr1
  const { length: length2 } = sortArr2
  const resArr = []
  for(let i = 0,j = 0; i < length1 && j < length2;) {
    if (sortArr1[i] === sortArr2[j]) {
      resArr.push(sortArr1[i])
      i++;
      j++;
    } else {
      sortArr1[i] > sortArr2[j] ? j++ : i++
    }
  }
  return resArr
}
console.log(intersection([2,2], [1,2,2,3]))

上述方法中,自己先用排序方法将数组进行从大到小的排序,接着利用两个浮标从数组头部开始一边比较,一边后移,若两个浮标所在的元素相等,则加入到并集数组中,否则,元素较小的元素所在的浮标往后移动一位,直到某个浮标移动到一个数组的队尾为止。 然而,数组排序毕竟有太大的局限性,当数组中的元素类型五花八门时,排序并不是一个好的选择,因此,为了兼容更多的类型,自己采用了如下方式实现了数组交集的功能:

Array<any>

function intersection (arr1, arr2) {
  const copyArr1 = [...arr1]
  const copyArr2 = [...arr2]
  const resArr = []
  while(copyArr1.length) {
    const header = copyArr1.shift()
    const index = copyArr2.findIndex(item => item === header)
    if (index > -1) {
      resArr.push(header)
      copyArr2.splice(index, 1)
    }
  }
  return resArr
}
const testObj = {a:1}
console.log(intersection([6, 2, 2,'a',3, 5, testObj, null, null], [1, 2, testObj, 2, 3, 'b', 'a', null, null]))

上述方法利用对对碰的消除策略,不间断的去除第一个数组的头部元素,当头部元素满足交集条件时就将该元素从另一个数组中扣去用来防止后续出现重复元素时影响交集判断。这样我们便实现了一个满足所有类型数组的交集方法。

基于上述求数组交集的方法,我们自然而然的可以得到求数组并集和差集的方法:

并集

function union (arr1, arr2) {
  const copyArr1 = [...arr1]
  const copyArr2 = [...arr2]
  const intersectionArr = []
  const subtractionArr = []
  while(copyArr1.length) {
    const header = copyArr1.shift()
    const index = copyArr2.findIndex(item => item === header)
    if (index > -1) {
      intersectionArr.push(header)
      copyArr2.splice(index, 1)
    } else {
      subtractionArr.push(header)
    }
  }
  return [...subtractionArr, ...intersectionArr, ...copyArr2]
}
const testObj = {a:1}
console.log(union([6, 2, 2,'a',3, 5, testObj, null, null], [1, 2, testObj, 2, 3, 'b', 'a', null, null]))

差集

function subtraction (arr1, arr2) {
  const copyArr1 = [...arr1]
  const copyArr2 = [...arr2]
  while(copyArr1.length) {
    const header = copyArr1.shift()
    const index = copyArr2.findIndex(item => item === header)
    if (index > -1) {
      copyArr2.splice(index, 1)
    }
  }
  return copyArr2
}
const testObj = {a:1}
console.log(subtraction([6, 2, 2,'a',3, 5, testObj, null, null], [1, 2, testObj, 2, 3, 'b', 'a', null, null]))

以上就是本篇文章的所有内容,感谢大家的阅读