js数组去重是前端面试中经常被问的题目,考察了面试者对js的掌握,解决问题的思路,以及是否具有专研精神。曾经一位前端界大神告诉我,解决问题的方式有很多种,解决问题时多问问自己还有没有其他的方法,探求最优解决方案才能学到更多
如果,这篇文章有幸被您阅读,文中出现的错误,或者您有其他的解决方案请在评论区告诉我,谢谢。


方案一

 /**
   * 1.构建一个新数组
   * 2.遍历目标数组,依次取出每一个元素
   * 3.将取出的元素与新数组里面的所有元素进行比较,
   *    如果没有出现 -> 该元素添加到新数组中,
   *    如果出现  -> 处理下一个目标数组元素
   * */
  function distinct(arr) {
    console.time();    //跟踪方法的占用时长
    var result = [];    // 构建结果数组result
    for (var i = 0, len = arr.length; i < len; i++) {
      for (var j = 0, rlen = result.length; j <= rlen; j++) {
        if (arr[i] === result[j]) {
          break;
        }
        if (j == result.length) {
          result.push(arr[i]);
        }
      }
    }
    console.timeEnd();
    return result;
  }
方案优点:
  • 结果数组与目标数组的顺序保持一致
  • 思路简单,兼容性好
方案缺点:
  • 速度慢

方案二

/**
   *1.目标数组排序
   *2.遍历目标数组,检测数组中的第i 个元素与结果数组中最后一个元素是否相同,如果不同,则将该元素添加到结果数组中
   * */
  function distinct(arr) {
    console.time();
    var result = [];
    arr = arr.sort();
    for (var i = 0, len = arr.length; i < len; i++) {
      if (arr[i] !== result[result.length - 1]) {
        result.push(arr[i])
      }
    }
    console.timeEnd();
    return result;
  }
方案优点:
  • 方案中先排序,后遍历,速度比方法一快
方案缺点:
  • 方案中使用了数组排序sort,打乱了原有顺序

Tips:数组排序

js中提供了数组排序方法sort,使用时需要注意以下几点:

  1. 调用sort方法时改变了目标数组本身,非生成新数组
  2. sort方法默认按照字符顺序进行排序,不过提供了回调方法,可以自定义排序规则

现有一数组arr:1,11,23,56,3,4,5,7,562,67

按字符排序
arr.sort() // 1, 11, 23, 3, 4, 5, 56, 562, 67, 7
按数字大小:正序
arr.sort((a,b) => a-b) // 1, 3, 4, 5, 7, 11, 23, 56, 67, 562
按数字大小:倒序
arr.sort((a,b) => b-a) // 562, 67, 56, 23, 11, 7, 5, 4, 3, 1

方案三

/**
   * 利用ES6的 数据结构SET的无重复值特性
   * Array.from 将类数组转换成数组
   * */
  function distinct3(arr) {
    console.time();
    var result = Array.from(new Set(arr));
    console.timeEnd();
    return result;
  }
方案优点:
  • 代码简洁,执行速度快
方案缺点:
  • ES6语法,使用时需要考虑兼容性问题

方案四

 /**
   * 利用对象属性无重复的特点
   * 遍历目标数组,将值设置为对象属性
   * Object.keys 将对象的所有属性提取成一个数组
   * */
  function distinct(arr) {
    console.time();
    var result = {};
    for (var i = 0, len = arr.length; i < len; i++) {
      result[arr[i]] = '';
    }
    result = Object.keys(result);
    console.timeEnd();
    return result;
  }
方案优点:
  • 速度快
方案缺点:
  • 1 与 '1' 无法区分
  • 结果数组中的值全部为字符串
  • 占内存,相当于利用空间换时间

方案五

/**
   * Array.filter 数组过滤函数,只保留符合条件的值
   * indexOf 查找元素第一次出现的位置,所有第1次之后查找的元素位置都不符合条件
   * */
  function distinct(arr) {
    console.time();
    var result = arr.filter(function (elem, index, self) {
      return self.indexOf(elem) === index;
    });
    console.timeEnd();
    return result;
  }

测试

随机生成包含10000个数字的数组

function random() {
    var a = [];
    for (var i = 0; i < 10000; i++) {
      a.push(Math.ceil(i * Math.random()))
    }
    return a;
  }

现在执行上述去重方法,取5次测试结果的平均值:

从执行速度来看,方法四 < 方法三 < 方法二 < 方法五 < 方法一
方法四最快,方法一最慢。但是五种方法各有优缺点,使用时要根据实际情况选择适合的方案。


写在最后

本篇文章旨在学习分享和记录,并不是说数组去重只有这五种方法,如果文章中出现了错误,或者您有更好的解决方案,麻烦您在评论区告知我,谢谢。

02-18 12:21