数组去重

130 阅读2分钟
const arr1 = [0, 0, '0', '0', 1, 1, '1', '1', undefined, undefined, 'undefined', 'undefined', null, null, 'null', 'null', NaN, NaN, true, true, 'true', 'true', false, false, 'false', 'false', Symbol(1), Symbol(1), 1n, 1n, {a: 1}, {a: 1}, [1], [1]]
const arr2 = [0, 0, '0', '0', 1, 1, '1', '1', undefined, undefined, 'undefined', 'undefined', null, null, 'null', 'null', NaN, NaN, true, true, 'true', 'true', false, false, 'false', 'false', Symbol(1), Symbol(1), {a: 1}, {a: 1}, [1], [1]]

Set + Array.from

Array.from(new Set(arr1) // [0, "0", 1, "1", undefined, "undefined", null, "null", NaN, true, "true", false, "false", Symbol(1), Symbol(1), 1n, {…}, {…}, Array(1), Array(1)]

由于arr1中{}和[]都是两个不同的引用地址,所以无法去重,若是同一引用地址则可去重;Symbol(1) !== Symbol(1),不存在去重)

for循环嵌套for循环1

遍历数组,让每一项与其他项进行比较,相同的则使用splice删除(无法去重NaN和不同引用地址的object,且会改变原数组):

const uniq = function(array) {
  for (let i = 0; i < array.length; i++) {
    for (let j = i + 1; j < array.length; j++) {
      if (array[i] === array[j]) {
        array.splice(j, 1)
        j --
      }
    }
  }
  return array
}
console.log(uniq(arr1)) // [0, "0", 1, "1", undefined, "undefined", null, "null", NaN, NaN, true, "true", false, "false", Symbol(1), Symbol(1), 1n, {…}, {…}, Array(1), Array(1)]

for循环嵌套for循环2

准备一个空数组result,遍历原数组,让其中每一项与空数组中每一项比较,遇到相同则break跳出循环,遍历到最后push进result(无法去重NaN和不同引用地址的object, 不会改变原数组):

const uniq = function(array) {
    const result = []
    for(let i = 0; i < array.length; i ++) {
    let j = 0
        for(j; j < result.length; j ++) {
            if(array[i] === result[j]) {
                break
            }
        }
        if(j === result.length) {
            result.push(array[i])
        }
    }
    return result
}
console.log(uniq(arr1)) // [0, "0", 1, "1", undefined, "undefined", null, "null", NaN, NaN, true, "true", false, "false", Symbol(1), Symbol(1), 1n, {…}, {…}, Array(1), Array(1)]

for循环嵌套for循环使用indexOf简化

const uniq = function(array) {
    const result = []
    for(let i = 0; i < array.length; i ++) {
        if(result.indexOf(array[i]) === -1) {
            result.push(array[i])
        }
    }
    return result
}
console.log(uniq(arr1) // [0, "0", 1, "1", undefined, "undefined", null, "null", NaN, NaN, true, "true", false, "false", Symbol(1), Symbol(1), 1n, {…}, {…}, Array(1), Array(1)]

for循环嵌套for循环使用includes可去重NaN

const uniq = function(array) {
    const result = []
    for(let i = 0; i < array.length; i ++) {
        if(!result.includes(array[i])) {
            result.push(array[i])
        }
    }
    return result
}
console.log(uniq(arr1) // [0, "0", 1, "1", undefined, "undefined", null, "null", NaN, true, "true", false, "false", Symbol(1), Symbol(1), 1n, {…}, {…}, Array(1), Array(1)]

filter + indexOf:

indexOf返回的是找到的元素的第一个索引,遍历数组,只返回indexOf后与当前项索引相等的元素(无法去重不同引用地址的object,会直接去掉NaN,不会改变原数组)

console.log(arr1.filter((item, index, source) => source.indexOf(item) === index)) // [0, "0", 1, "1", undefined, "undefined", null, "null", true, "true", false, "false", Symbol(1), Symbol(1), 1n, {…}, {…}, Array(1), Array(1)]

for循环 + findIndex:

使用findIndex可以对每一项进行操作,将每一项深拷贝后再进行比较,可以去重不同引用地址的object,会直接去掉NaN和Symbol,不改变原数组)

const uniq = function(array) {
  const result = []
  for(let i = 0; i < array.length; i ++) {
      if(result.findIndex(item => JSON.stringify(item) === JSON.stringify(array[i])) === -1) {
          result.push(array[i])
      }
  }
  return result
}
console.log(uniq(arr2)) // [0, "0", 1, "1", undefined, "undefined", null, "null", true, "true", false, "false", {…}, Array(1)](JSON.stringify无法转换bigInt类型)