zoukankan      html  css  js  c++  java
  • 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。

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

  • 相关阅读:
    二项队列
    左式堆
    优先级队列
    web.xml配置文件中<async-supported>true</async-supported>报错的解决方案
    Struts2中关于"There is no Action mapped for namespace / and action name"的总结
    spring四种依赖注入方式
    Spring @Resource、@Autowired、@Qualifier的注解注入及区别
    CXF自动生成客户端
    maven update 以后报错。
    Mavne + Spring整合CXF
  • 原文地址:https://www.cnblogs.com/liao123/p/14206866.html
Copyright © 2011-2022 走看看