JS实用功能-9、面试中常遇见的数组去重

JS数组去重是面试中并不少见的问题,听起来很简单,当你兴高采烈地回答了你的方法之后,你以为这道题就结束了吗?No,一般来说,面试官会继续问你“除了你刚刚说的方法,还有其他更好的方法吗?”,这时的你就需要了解多几种JS数组去重的方法了。

下面我们先来看看常见的去重方法先吧。

 一、双重for循环

拿前一个数据和后面的数据做对比,与后面相同的就删除。

//方法1
const unique = arr => {
  if(!(arr instanceof Array) || arr.length == 0){
    console.log('数组数据异常');
    return;
  }
  for(let i = 0; i < arr.length; i++){
    for(let j = i+1; j < arr.length; j++){
      if(arr[i] === arr[j]){
        arr.splice(j,1); //删除重复数据
        j--;
      }
    }
  }
  return arr;
}

测试数据:

let arr = [1,1,false,false,true,true,null,null,undefined,undefined,NaN,NaN,{},{},'a','a'];

测试结果:

 

 

 在结果中可以看出,部分相同的数据都已经被去掉了,但是true、NaN、{}这三个是没有去除的。应该是“==”判断的问题。

可以来看看NaN的情况:

 

 

 两个NaN对比,居然是个false,难怪没有去重成功。其他应该也是相对如此的,那么这种去重方法还是存在不足的。

二、单个for循环和indexOf

遍历原数组,将每个元素插入到新数组中。插入前先判断新数组中是否存在改元素。利用数组的indexOf方法来查重,有就返回元素在数组中的下标,不存在就返回-1.

const unique = arr => {
 .....
let arr1 = [];// 新建一个数组来存放arr中的元素 for(let i = 0; i < arr.length; i++){ if(arr1.indexOf(arr[i]) == -1){ arr1.push(arr[i]); } } return arr1; }

测试数据:

let arr = [1,1,false,false,true,true,null,null,undefined,undefined,NaN,NaN,{},{},'a','a'];

输出结果:

 

 

 看来这个对true去重有作用了呀,但是NaN、{}还是不起作用。

三、单个for循环和includes

这个跟第二个差不多,不同的是重复判断用的是数组的includes方法,它返回是Boolean类型,如果包含某个元素就返回true,反正false。

const unique = arr => {
  .....
  let arr1 = [];// 新建一个数组来存放arr中的元素
  for(let i = 0; i < arr.length; i++){
      if(!arr1.includes(arr[i])){
          arr1.push(arr[i]);
      }
  }
  return arr1;
}

测试数据:

let arr = [1,1,false,false,true,true,null,null,undefined,undefined,NaN,NaN,{},{},'a','a'];

输出结果:

  这次比前两次好了很多,能判断NaN了。

四、单个for循环和sort

先用sort方法对数组进行排序,然后对比相邻两个元素是否相等,做去重处理。

const unique = arr => {
 ..... arr
= arr.sort(); let arr1 = [arr[0]]; for(let i = 1;i < arr.length;i++){ if(arr[i] !== arr[i-1]){ arr1.push(arr[i]); } } return arr1; }

测试数据:

let arr = [1,1,false,false,true,true,null,null,undefined,undefined,NaN,NaN,{},{},'a','a'];

测试结果:

 

 

 效果还是很好的嘛。

五、ES6的Set集合

Set集合作为ES6新加入的数据结构,存储类似于数组,但是里面的元素是不能重复的。我们可以先将数组转成Set集合,去重之后,再转为数组输出。

const unique = arr => {
 .....
return Array.from(new Set(arr)) }

Array.from()方法就是将一个类数组对象或者可遍历对象转换成一个真正的数组,不过它也是ES6的新特性。

测试数据:

let arr = [1,1,false,false,true,true,null,null,undefined,undefined,NaN,NaN,{},{},'a','a'];

测试结果:

 

 

 看来效果还是很不错的啊,除了 {} 不能去重外,其他都完成了。

六、数组的filter函数

filter()会创建一个新数组,循环对数组中的元素调用callback函数, 如果返回true 保留,如果返回false 过滤掉,  返回新数组,老数组不变。

const unique = arr => {
  return arr.filter((item,index) => {
    return arr.indexOf(item) === index;
  });
}

测数据:

let arr = [1,1,false,false,true,true,null,null,undefined,undefined,NaN,NaN,{},{},'a','a'];

测试结果:

 

 

 这个方法也是除了 {} 无法去重外,其他都可以成功了。

七、ES6的Map对象

Map作为ES6的一种新型数据结构,类似json,用键值对方式存储数据。Map中有has()方法,返回一个Boolean类型,来表明Map中是否存在指定元素。

const unique = arr => {
  .....
  let map = new Map();
  let arr1 = []
  for (let i = 0; i < arr.length; i++) {
      if (map.has(arr[i])) {      // 判断是否存在该key值
          map.set(arr[i], true);
      }
      else {
          map.set(arr[i], false);
          arr1.push(arr[i]);
      }
  }
  return arr1;
}

测试数据:

let arr = [1,1,false,false,true,true,null,null,undefined,undefined,NaN,NaN,{},{},'a','a'];

测试结果:

 

 

 也是除了{}去不了重之外,其他都正常。

八、递归

这种方法其实跟第一种方法差不多,通过循环判断前一个元素和后面元素是否相同来查重。不过要求掌握递归算法的。

const unique = arr => {
  let arr1 = arr;
  let len = arr1.length;
  function loop(index){
    if(index >= 1){
      if(arr1[index] === arr1[index-1] ){
          arr1.splice(index,1);
      }
      loop(index - 1);  // 递归loop,然后数组去重
    }
  }
  loop(len-1);
  return arr1;
}

测试数据:

let arr = [1,1,false,false,true,true,null,null,undefined,undefined,NaN,NaN,{},{},'a','a'];

测试结果:

 

 

 处理NaN和{}无法去重外,其他都没问题。

上面的方法都能解决日常开发中的大部分去重问题,但都不能解决 {} 去重问题,难道就真的没办法了吗?

对象是永不相等的,在用 === 号的情况下,因为它们属于引用类型,在三等符号的情况下判断是内存地址了,当且仅当它们引用同一个基对象时,它们才相等。

九、Map和Set对JSON数组去重

其实可以将对象转换成字符串,然后让字符串对比,就可以做到去重的效果。

const unique = arr => {
  const map = new Map()
  return arr.filter( item => !map.has(JSON.stringify(item)) && map.set(JSON.stringify(item), 1));
}

测试数据1:

let json = [{},{}];

测试结果1:

 

 测试数据2:

let json2 = [{a: 1, b: 2}, {a: 1, b: 2}];

测试结果2:

 

 通过上面的方法也就很好的解决了 对象 相等的问题,其实知道原理之后,用for循环也是可以解决的,但是,最近在学ES6,顺便装一下13。

上面就是这篇的全部内容了。

posted @ 2020-12-30 18:11  padding2020  阅读(156)  评论(0编辑  收藏  举报
想了解更多的,大家也可以关注我的公众号:padding2020