浅谈Javascript数组去重

javascript 数组 array 去重 distinct unique

恰好前天口试的时刻口试官问到了数组去重的题目,当时有点语塞只想到用了两个轮回检测(实在迷迷糊糊想到了hash的要领做然则由于记得不清不敢说= =!),思绪是检测是不是有元素反复,然后将只涌现一次的元素推入到新数组中,然后返回新数组。然后口试官又问这类要领的时候效力,因而黑线了。so这两天看了一下相干的文章,在这里也总结一下javascript数组去重的要领。

两层轮回检测反复元素法

起首,引见一下人人都邑想到的两层轮回的demo,以下例:

function distinct(arr) {
    var ret = [],
        length = arr.length;
    for(var i = 0;i < length; i++){
        for(j = i+1; j<length;j++){
            if(arr[i] === arr[j]){
                j = ++i;
            }
        }
        ret.push(arr[i]);
    }
    return ret;
}
var arra = [1,2,3,4,4,1,1,2,1,1,1];
distinct(arra);                              //返回[3,4,2,1]

<!–more–>
如上的代码完成是轻松易得的,思绪以下:

  1. 起首外层轮回比遍历全部数组

  2. 内层轮回婚配是不是有值反复

    a.如推断有雷同元素则自增i变量,跳出i的轮回
    b.如推断无时则将无相等值的元素推入到ret数组中

    3.返回ret。

长处:便利易懂,大多数顺序员能想到。
瑕玷:很明显时候斲丧太高,两层轮回时候斲丧太多,时候的斲丧为O(n^2^),在举行大批数据处置惩罚时会斲丧大批资本。而且该要领没法处置惩罚字符和数组,以下例:

var arr = [1,23,4,5,6,7,'1',22,3,1,2];
distinct(arr);                  //返回[23, 4, 5, 6, 7, "1", 22, 3, 1, 2]

所以我们能够最先斟酌一些别的要领优化数组去重:

sort重排数组去除反复元素索引法(!每个浏览器中的sort函数的排序要领并不一样,所以完成效果能够会有差别,经测试在chrome下测试别的数组完成会涌现题目)

这类要领就是先讲原数组运用sort要领将数组重排,以取得将雷同元素为相邻位的一个新数组。该要领以下:

function distinct(arr){
    var self = arr;
        list = self.concat().sort();
        
    list.sort(function(a, b){
        if(a === b){
            var ind = self.indexOf(a);
            self.splice(ind, 1);
        }
    });
    return self;
}
var arra = [1,2,3,3,1,1,1,'1'];
var arr = distinct(arra);                //返回的数组为[2,3,1,'1']

一样的,在运用这类要领的重排的时刻,依然会有肯定的资本斲丧,在sort()函数中回调函数是运用的冒泡排序,而冒泡排序的效力并不高。然则运用这类要领的效力依然比上一种要领的效力高,由于在此例中只涌现了一次轮回遍历。

长处:顺序简约,效力较高。
瑕玷:1.依然没法处理数字1和字符’1’的去除。2.依靠indexOf要领,我们晓得在IE6~8中并未支撑indexOf()要领。
所以我们还要做一些兼容性的处置惩罚。以下:

var indexOf = [].indexOf ?
    function indexOf(arr, item){
        return arr.indexOf(item);
    }:
    function indexOf(arr, item){
        for(var i = 0; i < arr.length; i++){
            if(arr[i] === item){
                retrun i;            
            }
        }
        return -1;
    }
    
function distinct(arr){
    var self = arr;
        list = self.concat().sort();
        
    list.sort(function(a, b){
        if(a === b){
            var ind = self.indexOf(arr, a);
            self.splice(ind, 1);
        }
    });
    return self;
}    

将数组元素值存为对象的属性

function distinct(arr) {
    var ret = [],
        json = {},
        length = arr.length;
        
    for(var i = 0; i < length; i++){
        var val = arr[i];
        if(!json[val]){
            json[val] = 1;
            ret.push(val);
        }
    }
    return ret;
}

var arra = [1,2,3,5,7,1,2,'1'];

以上要领越发的简约,而且也能在本来的基础上辨别字符‘1’和数字1的区分。
在此例中思绪以下:
1.轮回遍历每个元素
2.检测在json对象中是不是含遍历到的元素的值

a: 假如是则跳过
b: 假如否存入json对象中该属性名的值设为1

3.将存入对象了元素的值推入到新数组中,返回新数组。

总结,实在数组去重不过就是推断一个元素在数组中是不是有反复的值。优化也是一向转变剖断元素是不是反复的一些技能,如例1中是遍历数组,例2是重排数组取得索引,例3则别开生面将元素的值作为对象的属性。

参考自:
从 JavaScript 数组去重谈机能优化
也谈javascript数组去重
js数组去重

感谢@飞的更高 指出的题目

同步于个人博客:http://penouc.com

    原文作者:penouc
    原文地址: https://segmentfault.com/a/1190000000513057
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞