数组去重方法分析

数组去重方法分析

方法一、通过新数组的indexOf方法

 

 1 Array.prototype.unique = Array.prototype.unique || function () {
 2     var result = [];
 3     this.forEach(function (v) {
 4         if(result.indexOf(v) < 0){
 5             //result.indexOf(v) >= 0 表示这个 v 已经在数组result[]里面了
 6             // < 0 则表示这个 v 还没在数组里面 没有的才push   有的就不push了  所以不会出现两个相等的 v 。
 7             result.push(v);
 8         }
 9     });
10     return result;
11 };

方法二、通过原数组的indexOf方法

 

 1 Array.prototype.unique = Array.prototype.unique || function () {
 2         var result = [];
 3         for(var i = 0; i <this.length; i++) {
 4             if (this.indexOf(this[i]) == i) {
 5                 //this.indexOf(this[i]) !== i 表面这个元素已经出现过了  == i表示第一次出现,这时才push到result里面去。
 6                 result.push(this[i]);
 7             }
 8         }
 9         return result;
10     };

方法三、使用hash表

 

 1 Array.prototype.unique = Array.prototype.unique || function () {
 2         var hash = {}; //新建一个hash表
 3         var result = []; //新建一个数组
 4         for (var i = 0; i <this.length; i++){
 5             if(!hash[this[i]]){  //如果hash表中没有这项
 6                 hash[this[i]] = true;  //就把这项添加到hash表中去
 7                 result.push(this[i]);  //并且把这项添加到新数组
 8             }
 9         }
10         return result;
11     };

        为了检验三种方法性能的优劣,我写了一个测试程序 ,这里我创建 一个长度为len的数组,数组的每一项为0 - wth的随机数组,给len和wth赋不同值,再在network里面看他们各自执行时间。

1     var len = 1000, wth = 1000;
2     var arr = new Array(len);
3     for(var i = 0; i < wth; i++){
4         arr[i] = Math.floor(Math.random()*wth);
5     }
6     console.log(arr.unique());

        检验数组长度和纬度不同时三种方法的效率(chrome浏览器下),结果如下:

1、当 len =1000, wth = 1000时

        三种方法执行时间基本一样,都在30ms左右;

2、设置 len = 1000, wth = 10000时

       三种方法执行时间按顺序分别为:100ms左右、120ms左右、38ms左右;

3、设置len =  10000, wth = 10000时

       此时测试出来的时间与第二种设置基本一样! 

4、设置len  =100000,wth = 10000时

       三种方法执行时间按顺序分别为:120ms左右、9~10s之间、60ms左右;

5、设置len = 100000,wth = 100000时

      三种方法执行时间分别为:6-7s之间、9~10s之间、60ms左右

 

数据很明显:时间上最稳定的方式是第三种--hash表法,其余两种什么鬼啊....

       当数组长度纬度较小时,用indexOf方法种方法勉强完成任务,性能劣与hash表法,其中方法一优于方法二;

       当数组长度纬度较大时,6-7s是什么鬼...9-10秒又是什么鬼...这个时候这两种方法都只有gg。。。

 

简单分析一下:

      第一二中方法用到了数组的indexOf方法,这种方法会寻找参数再数组中第一次出现的位置,很显然,js引擎在实现这个方法是会遍历数组直到找到目标为止,

      所以这种方法会消耗很多时间。

      第三种方法用的是hash表,把已经出现过的通过下标的形式存入一个Object内,而下标的引用要比用indexOf搜索数组快很多!当然,这种方法也不是完美的,

      因为多了一个hash表,内存占用更多,相当于用空间换时间。。

方法四、Set结构法

 

      ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。

      Set 本身是一个构造函数,用来生成 Set 数据结构。看看下面的代码。

1     const s = new Set();
2     [1,3,2,3,6,7,2].forEach(x => s.add(x));
3     console.log(s);
4     //{1,3,2,6,7}

      运行结果是{1,3,2,6,7},很显然这不是一个数组。要将它转化为一个数组,那再看看下面的方法。

1  const set = new Set([1,2,3,2,5]);
2     const array = Array.from(set);
3     console.log(array);
4     //[1,2,3,5]

      这里用到了Array的from方法,其实还可以封装一个利用set结构转数组的方法,如下:

1     function derepetition(array){
2         return Array.from(new Set(array));
3     }
4     console.log(derepetition([1,3,2,3,5]));
5     //[1,3,2,5]

      其实还有更简便的方法...

1     const set1 = new Set([1,2,3,3,5]);
2     [...set1];  //[1,2,3,5]

      这里就简直不讲道理了,不过是真心的简便!!!!

 

posted on 2017-08-14 21:22  cdut007  阅读(138)  评论(0编辑  收藏  举报

导航