专栏首页FEWYJavaScript 数组去重的多种方法原理详解

JavaScript 数组去重的多种方法原理详解

说明

数组去重,这是一个面试经常会遇见的问题,网上讲数组去重的文章也是特别的多,但是我们依旧来讲讲数组去重,这篇文章比较适合于接触过一段时间的JavaScript的初学者,希望这篇文章能给初学者带来一些帮助。

方法一

function unique(arr)
{
    var result = []; //结果数组
    for(var i = 0; i < arr.length; i++) 
    {
        //如果在结果数组result中没有找到arr[i],则把arr[i]压入结果数组result中
        if (result.indexOf(arr[i]) == -1) result.push(arr[i]);
    }
    return result;
}

方法二

Array.prototype.unique = function()
{
    var result = [this[0]]; //结果数组
    for(var i = 1; i < this.length; i++) //从第二项开始遍历
    {
        //如果调用unique()方法的数组的第i项在数组中第一次出现的位置是i,
        //那么表示第i项是不重复的,则存入结果数组
        if (this.indexOf(this[i]) == i) result.push(this[i]);
    }
    return result;
}

解释 方法一和方法二,看第一眼,可能没什么,等你把两个方法弄明白,才发现区别真的不大,就像是同一个人只是换了件衣服而已。 好吧,我们看看这个人是谁,要说这个人是谁,重点在于for循环、indexOf( )方法和push( )方法。 for循环就不必多做解释了,既然接触过JavaScript一定是明白的 在Array 对象中 indexOf( )方法搜索数组中的元素,并返回它首次出现的位置,如果没找到则返回 -1。 在String 对象中 indexOf( ) 方法可返回某个指定的字符串值在字符串中首次出现的位置,如果没找到则返回 -1。 注意: JavaScript中的Array对象 和 String对象都是具有indexOf( )方法的,而且用法是一样的。 对于indexOf( )不是很理解的朋友点这里

push( ) 方法可向数组的末尾添加一个或多个元素,并返回新的长度。 push( )方法是Array对象中的方法,String对象中没有。 对于push( )不是很理解的朋友点这里

那衣服是什么呢?我们继续说,方法一,是定义了一个函数unique,传入的参数没有限制,也就是说,不管是谁都可以用这个方法,看图

数组能用这个方法,字符串也能用这个方法。 而方法二是在Array对象中添加了一个unique( )方法,这样的话,就只能是数组才能用这个方法了,看图

用字符串去调用这个方法,报错了,因为字符串没有这个方法,只有数组有,这样就多了一种限制。

方法三

function unique3(arr){
    //遍历arr,同时创建结果数组result
    for(var i=0,result=[];i<arr.length;i++){
    //遍历结果数组result
        for(var j=0;j<result.length;j++){
            //如果result中有一个元素等于arr[i],就退出循环
            //说明arr[i],是一个重复的元素
            if(result[j]===arr[i]){break;}
        }//遍历结束
        //如果j等于result的length,就把arr[i],压入数组result
        //j等于result的length,说明遍历到了最后,也就是没有找到相同的元素
        if(j===result.length){
                result[result.length]=arr[i];
        }
    }
    return result;//返回result
}

方法四

Array.prototype.unique4 = function(){
     //创建结果数组,值为调用unique4()方法的数组的第一个元素
     var result = [this[0]];
     //遍历 调用unique4方法的数组
     for(var i = 1; i < this.length; i++){
          //声明一个变量 repeat,判断元素是不是重复
          var repeat = false;
          //遍历结果数组 result
          for(var j = 0; j < result.length; j++){
            //如果结果数组result中的一个元素,等于,调用unique4()方法的数组的其中一个元素,repeat值为true,跳出循环
            //也就是结果数组result中的这个元素和调用unique4()方法的数组中的元素重复了
           if(this[i] === result[j]){
            repeat = true;
            break;
           }
          }
          //如果结果数组result中的一个元素,不等于,调用unique4()方法的数组的其中一个元素,repeat值为false,把元素添加到结果数组
          //也就是结果数组result中的这个元素和调用unique4()方法的数组中的元素不重复
          if(!repeat){
           result.push(this[i]);
          }
     }
//   返回结果数组result
     return result;
}

解释 我相信,你已经看出来了,方法三和方法四的区别也不大,能明白其中一个,另外的也一样!这两个方法,看上去代码挺多,你可以去掉注释看看,其实也不多,主要的就是两层for循环罢了,而内层的for循环其实是实现了一下indexOf( )的功能。

方法五

function unique5(arr){
// 创建结果数组
 var result = [];
 //创建hash对象,用来代替indexOf
 var hash = {};
 for(var i = 0; i < arr.length; i++){
  //key就是数组元素的类型+数组元素,用来区分number和"number"
  var key = typeof(arr[i]) + arr[i];
  //如果hash对象中的key属性值不等于1(说明hash对象中不存在key属性),就把arr[i]压入结果数组result,同时设置hash的key属性值为1
  if(hash[key]!==1){
      result.push(arr[i]);
      hash[key] = 1;
    }
 }
 return result;
}

方法六

Array.prototype.unique6=function(){
     // 创建结果数组
     var result = [];
     //创建hash对象,用来代替indexOf
     var hash = {};
     for(var i=0;i<this.length;i++){
        // hash[this[i]] ,这是看 hash 中是否有 this[i] 这个属性,如果有,该属性值就+1,这个值就是出现的次数
        if(hash[this[i]]){
             hash[this[i]]++;
        }
        //如果,hash中没有this[i]属性,则将this[i]压入结果数组result,同时给这个属性,赋值为1
        else{
             result.push(this[i]);
             hash[this[i]]=1;
        }
     } 
//最后返回了一个对象,包括了结果数组,和带次数的hash对象  
return {result,hash};
}

解释 好吧,方法五和方法六差不多,核心思想和前面的几种方法一样,但是还是有一些不同的,方法五中写var key = typeof(arr[i]) + arr[i];这句是因为在 JavaScript 里,对象的键只能是字符串,所以为了区分数组中的数字,和能转为数字的字符串,就需要这句了,而方法六就不能区分了,看图

方法七

Array.prototype.unique7 = function(){
    //先排序
    this.sort(); 
    //创建结果数组
    var result = [this[0]];
    /* 遍历 调用unique7()方法的数组 如果该数组中的第i项,
    不等于结果数组result中的最后一项,就把第i项,压入结果数组 */
    for(var i = 1; i < this.length; i++){
        if(this[i] !== result[result.length - 1]){
            result.push(this[i]);
        }
    }
    return result;
}

解释 这次终于是不一样了,思路已经换了,这次需要先把数组排序,这点很重要,排序之后,再进行比较,比较的是,调用方法的数组和结果数组,其实也就是在比较调用方法的数组中的,第i项和第i-1项,如果相等,就什么都不做,不相等就把第i项压入结果数组。

总结

这里这些方法我比较推荐用 方法五 和 方法七。 如果你认同这七种方法,可以算是解决数组去重问题的方法,那么我相信,你可以写出更多的方法来,如果你觉得这里很多的方法的思路是一样的,只能算是两种方法,我也同意。 如果你觉得这些方法太麻烦,看这里JavaScript数组去重—ES6的两种方式 这篇文章中的方法可能更适合你哦! 如果你还有什么更有趣方法,也欢迎分享出来。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 学习 canvas 的 globalCompositeOperation 做出的神奇效果

    最早知道 canvas 的 globalCompositeOperation 属性,是在需要实现一个刮刮卡效果的时候,当时也就是网上找到刮刮卡的效果赶紧完成任务...

    FEWY
  • JavaScript实现冒泡排序

    对数组进行 冒泡排序 算是比较简单的,冒泡排序也是容易理解的一种排序算法了,在面试的时候,很可能就会问到。

    FEWY
  • :before 和 :after的多用途实践 — 特效篇(3)

    按钮一 先利用 :after 伪元素生成一个块级元素,刚开始,这个块级元素的宽虽然是100%,但是它没有高,所以会看不到,然后利用定位 和 转换 让它始终居...

    FEWY
  • Win下执行kettle的trans和job的批处理示例

    set panpath=C:\pdi-ce-5.4.0.1-130\data-integration set kpath=D:\03works\ZYWSPT\...

    用户5640963
  • 程序员算法面试中,必须掌握的数组理论知识

    数组是非常基础的数据结构,在面试中,考察数组的题目一般在思维上都不难,主要是考察对代码的掌控能力

    代码随想录
  • PHP-数组

    数组可以使单个变量中存储多个值的特殊变量,php中的数组使用array();来定义,或者用[]来定义,php中的数组相当于python中的列表。在php中,有三...

    行 者
  • VBA数组(一)基础知识

    大家好,前面介绍过VBA变量,可以通过它来访问数据。但对于大量数据时候,通过声明变量就显得太繁琐,此时就可以通过数组来访问数据解决。

    无言之月
  • 利用Python进行数据分析(5) NumPy基础: ndarray索引和切片

    一维数组的切片语法格式为array[index1:index2],意思是从index1索引位置开始,到index2索引(不包括index2)位置结束的一段数组。...

    公众号---志学Python
  • [Leetcode][双指针/多指针]相关题目汇总/分析/总结

    后端技术漫谈
  • 最大子数组差

    题目链接: 45. 最大子数组差 给定一个整数数组,找出两个不重叠的子数组A和B,使两个子数组和的差的绝对值|SUM(A) - SUM(B)|最大。 返回这个最...

    echobingo

扫码关注云+社区

领取腾讯云代金券