您的位置:首页 > Web前端 > JavaScript

js数组去重的4个方法+1

2016-12-03 15:00 134 查看
Array.prototype.unique1 = function()
{
var n = []; //一个新的临时数组
for(var i = 0; i < this.length; i++) //遍历当前数组
{
//如果当前数组的第i已经保存进了临时数组,那么跳过,
//否则把当前项push到临时数组里面
if (n.indexOf(this[i]) == -1) n.push(this[i]);
}
return n;
}


Array.prototype.unique2 = function()
{
var n = {},r=[]; //n为hash表,r为临时数组
for(var i = 0; i < this.length; i++) //遍历当前数组
{
if (!n[this[i]]) //如果hash表中没有当前项
{
n[this[i]] = true; //存入hash表
r.push(this[i]); //把当前数组的当前项push到临时数组里面
}
}
return r;
}


    其中第1种用到了数组的indexOf方法。此方法的目的是寻找存入参数在数组中第一次出现的位置。很显然,js引擎在实现这个方法的时候会遍历数组直到找到目标为止。所以此函数会浪费掉很多时间。 而第2中方法用的是hash表。把已经出现过的通过下标的形式存入一个object内。下标的引用要比用indexOf搜索数组快的多。

    为了判断这两种方法的效率如何,我做了一个测试程序,生成一个10000长度的随机数组成的数组,然后分别用几个方法来测试执行时间。 结果表明第二种方法远远快于其他两种方法。 但是内存占用方面应该第二种方法比较多,因为多了一个hash表。这就是所谓的空间换时间。 

第三种方法:
Array.prototype.unique4 = function()
{
this.sort();
var re=[this[0]];
for(var i = 1; i < this.length; i++)
{
if( this[i] !== re[re.length-1])
{
re.push(this[i]);
}
}
return re;
}


    这个方法的思路是先把数组排序,然后比较相邻的两个值。 排序的时候用的JS原生的sort方法,JS引擎内部应该是用的快速排序吧。 

第二种方法有个局限,就是作为下标会被转换为字符串,这样1, '1'等不同类型的值会对应到同一个下标而被去重,但实际应该保留。

把 hash 表的值从 true 改为一个数组,里面保存出现过的类型就行了。

最终方法:四.

[javascript] view
plain copy

Array.prototype.unique = function()  

{  

    var n = {}, r = [], len = this.length, val, type;  

    for (var i = 0; i < this.length; i++) {  

        val = this[i];  

        type = typeof val;  

        if (!n[val]) {  

            n[val] = [type];  

            r.push(val);  

        } else if (n[val].indexOf(type) < 0) {  

            n[val].push(type);  

            r.push(val);  

        }  

    }  

    return r;  

}  

测试:var arr=[];
  for(var i=0;i<1000000;i++){

          arr.push(parseInt(Math.random()*1000));
  }

       console.time("时间");

       arr=arr.unique3();

       console.timeEnd("时间");

       console.log(arr);

第一种:810.859ms

第二种:13.029ms  但存在缺陷

第三种:789.781ms

第四种最终方法;20.117ms

结论:第四种方法快了太多了

还有一种方法利用数组的 filter 方法,可根据条件过滤数组。

var a = [1,2,2,3,4,5,6,7];
var b = a.filter(function(v){
    return
v % 2 === 0;
});
console.log(a);  //
->[1,2,2,3,4,5,6,7]
console.log(b);  //
->[2,2,4,6]

数组的 filter 方法,可根据条件过滤数组。
遍历数组,将 filter 的参数 function(v){..} 返回为 false 时的值滤掉,但不改变原数组。

方法五:

var arr = [3,5,2,6,2,3,5,8,6]

function distinct(arr) {
return arr.filter(function (elem,index,arr){
return arr.indexOf(elem,index+1) === -1;  //判断当前元素之后没有与之相同的元素,则返回true
});
}

console.log(distinct(arr));

思路很好,但是测试耗时太长居然要8000多ms
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: