JS面试手写:数组去重

48 阅读1分钟

基本情况:数组中存储的都是基本数据类型

方式一:

// ES5
let test = [1,2,3,1,3,5,2,4,6]
function unique( arr ) {
  let res  = arr.filter( function(item, index, array) {
    return array.indexOf(item) === index
  })

  return res
}

console.log(unique(test))

方式二:

// ES6
let unique2 = arr => [...new Set(arr)]

console.log(unique2(test))

方式三:

// 算法实现
// 使用一个同向指针
function unique3( arr ) {
  if(!arr || arr.length === 0) return []

  arr.sort( (a,b) => a - b )

  let i, j = 1 
  for(i = 0; i < arr.length; i++) {
    while(j < arr.length && arr[j] === arr[i]){
      j++
    }
    if(j >= arr.length)
      break
    arr[i + 1] = arr[j]
  }

  return arr.slice(0, i + 1)
}
console.log(unique3(test));

方式四:一种特殊的解法

声明一个对象,然后将该数组的元素作为对象的属性名,属性值随便设,然后利用对象属性名不会重复的特点可得到一个对象。接下来再利用Object.keys()拿到属性名。

let test = [1,2,3,1,3,5,2,4,6]
function unique4(arr) {
  let newObj = {};
  arr.forEach((item) => {
    newObj[item] = 0;
  });
  return Object.keys(newObj).map((item) => +item); //将元素处理成number
}

console.log(unique4(test))

特殊情况:数组中的元素还有引用数据类型:数组、对象,如:[1, 1, 2, 3, [4], [4], 5, 6, 6, { 7: 7 }, { 7: 7 }]

思路:元素转成JSON数据再对比,需要用到JSON.stringify()函数

let test = [1, 1, 2, 3, [4], [4], 5, 6, 6, { 7: 7 }, { 7: 7 }];
function unique(arr) {
  let newArr = [];
  arr.forEach((item) => {
    let isClude = false;
    newArr.forEach((item1) => {
      if (JSON.stringify(item) === JSON.stringify(item1)) {
        isClude = true;
      }
    });
    if (!isClude) {
      newArr.push(item);
    }
  });
  return newArr;
}

console.log(unique(test));

进一步优化:和上面基本数据类型去重的方法四一样,借助一个map + 遍历 优化时间复杂度

function unique (arr) {
  let newArr = []
  let obj = {}
  arr.forEach(item => {
    if (typeof item !== 'object') {
      if (newArr.indexOf(item) === -1) {
        newArr.push(item)
      }
    } else {
      let str = JSON.stringify(item)
      if (!obj[str]) {
        newArr.push(item)
        obj[str] = 1
      }
    }
  })
  return newArr
}