• array_unique


    方法一:双重遍历

    双重遍历是最容易想到的去重方案:

    1. 构建一个新的数组存放结果
    2. for循环中每次从原数组取出一个元素,用这个元素循环与结果数组对比
    3. 若结果数组中没有该元素,则存到结果数组中
    Array.prototype.unique=function(){
    	// 构建一个新数组,存放结果 
    	var newArray = [this[0]];
    	for (var i = 0; i<this.length; i++){
    		var repeat = false;
    		for(var j=0;j<newArray.length;j++){
    			if(this[i]===newArray[j]){
    				repeat=true;
    				break;
    			}
    		}
    		if(!repeat){
    			newArray.push(this[i]);
    		}
    	}
    	return newArray;
    }
    
    • 优点:思路简单、容易实现,用于去重的比较部分是自己编写实现(this[i]==newArray[j])。可以针对具体情况加以特殊处理。
    • 缺点:时间复杂度高,性能差。

    以下面这个测试案例进行比较:

    function test () { 
    	var arr = []; 
    	for (var i = 0; i < 1000000; i++) { 
    		arr.push(Math.round(Math.random(i) * 10000)); 
    	} 
    	doTest(arr, 1); 
    } 
    function doTest(arr, n) { 
    	var tStart = (new Date()).getTime(); 
    	var re = arr.unique(); 
    	var tEnd = (new Date()).getTime(); 
    	console.log('双重循环去重方法使用时间是:' + (tEnd - tStart) + 'ms'); 
    	return re; 
    } 
    test();
    

    在Chrome控制台中测试方法一,花费时间为:4006ms

    方法二:排序遍历去重

    先使用sort()方法对原数组做一个排序,排完序之后对数组做遍历,并且检查数组中的第i个元素与结果数组中最后一个元素是否相同。如果不同,则将元素放到结果数组中。

    Array.prototype.unique = function () { 
    	// 原数组先排序 
    	this.sort(); 
    	// 构建一个新数组存放结果 
    	var newArray = []; 
    	for (var i = 1; i < this.length; i++) { 
    	// 检查原数组中的第i个元素与结果中的最后一个元素是否相同 
    	// 因为排序了,所以重复元素会在相邻位置 
    		if(this[i] !== newArray[newArray.length - 1]) { 
    		// 如果不同,将元素放到结果数组中 
    			newArray.push(this[i]); 
    		} 
    	} 
    	return newArray; 
    }
    
    • 优点:速度快,只需要700ms
    • 缺点:去重后的数组会做排序、去重后的数组,与数字相同的数字字符无法区分,比如'12'12

    方法三:对象键值对法

    这种方法是利用了对象的key不可以重复的特性来进行去重。

    1. 创建一个JavaScript对象及新数组
    2. 使用for循环遍历原数组,每次取出一个元素与JavaScript对象的键做对比
    3. 如果不包含,将存入对象的元素值推入到结果数组中,并且将存入对象的该key的value设为1
    Array.prototype.unique=function() {
        var ret = [];
        var len = this.length;
        var tmp = {};
        for(var i=0; i<len; i++){
            if(!tmp[this[i]]){
                tmp[this[i]] = 1;
                ret.push(this[i]);
            }
        }
        return ret;
    }
    
    • 优点:速度快,只需要10ms
    • 缺点:去重后的数组,与数字相同的数字字符无法区分,比如'12'12,因为对象key只能为字符串;无法处理复杂数据类型,比如对象(因为对象作为key会变成[object Object]);特殊数据,比如'proto'会挂掉,因为tmp对象的'proto'属性无法被重写

    基于上面提到的缺点,有人提出了以下的改进措施:

    Array.prototype.unique=function() {
        var ret = [];
        var len = this.length;
        var tmp = {};
        var tmpKey;
        for(var i=0; i<len; i++){
            tmpKey = typeof this[i] + JSON.stringify(this[i]);
            if(!tmp[tmpKey]){
                tmp[tmpKey] = 1;
                ret.push(this[i]);
            }
        }
        return ret;
    }
    

    这个改进方法可以弥补上述提到的缺点,但是性能有所降低,去重速度达到了500ms左右,且内存占用较高,但依然是各个方案中最快的。

    方法四:Map Key

    ES2015中添加了Map这种新的数据类型,可以把它想象成key类型没有限制的对象,它的存取使用单独的get()、set()接口。与传统的对象相比,Map的key在使用中没有限制。

    Array.prototype.unique=function() {
        var ret = [];
        var len = this.length;
        var tmp = new Map();
        for(var i=0; i<len; i++){
            if(!tmp.get(this[i])){
                tmp.set(this[i], 1);
                ret.push(this[i]);
            }
        }
        return ret;
    }
    
    • 优点:执行速度快,43ms
    • 缺点:兼容性不高。

    方法五:Set

    除了Map以外,ES2015还引入了一种叫作Set的数据类型。它不允许重复元素出现。

    Array.prototype.unique=function(){
        var set = new Set(this);
        return Array.from(set);
    }
    
    • 优点:代码简单,执行速度较快,600ms左右。
    • 缺点:兼容性不高。

    总结

    去重的方法没有最正确的,也没有最优,应该具体问题具体分析,根据实际场景进行选择正确的方法。

    请使用手机"扫一扫"x

  • 相关阅读:
    linux___用户管理
    linux基础_vim命令
    linux
    linux_centos安装
    python基础1_哈希碰撞的认识
    oop对象,面向对象
    Oracle数据库—— 事务处理与并发控制
    Oracle数据库——索引、视图、序列和同义词的创建
    Oracle数据库——触发器的创建与应用
    Oracle数据库—— 存储过程与函数的创建
  • 原文地址:https://www.cnblogs.com/depsi/p/6423844.html
Copyright © 2020-2023  润新知