Javascript高性能数组去重

    当遇到大数据量处理时,前端的小姐姐、小哥哥们经常束手无策,然后小心翼翼去请教一些大神,大神们一般会看一眼,然后来一句: “脚本代码,动态语言,性能就那样,解决不了。”

但是事实真的解决不了吗? 未必。

性能的解决在于算法,无语言无必然关系,只要语言提供了支撑相应算法的特性,高性能就不再话下!

Part1. 上例子

闲话少叙,请看入下代码:

		function show(html)  {  document.write(html + "<br><br>");  }
		function  DelRepeatFun1(arr)   //函数1:采用IndexOf判断是否存在重复元素
		{
			var newarr = [];
			var len = arr.length;
			for(var i=0; i<len; i++)  { if(newarr.indexOf(arr[i])==-1)  { newarr.push(arr[i]); }  } 
			return newarr.length;
		} 
		function  DelRepeatFun2(arr)	//函数2:对象属性的机制,默认去重
		{
			var newarrobj = {};
			var len = arr.length;
			for(var i=0; i<len; i++)  { newarrobj[arr[i]]= 1; 	}
			var newarr = [];
			for(var n in newarrobj)  { newarr.push(n); }
			return newarr.length;
		} 
		function Test() 
		{

			var arr = [];
			//先构造一个20万级的数据量
			for(var i=0; i<200000; i++)   {  arr.push(   Math.floor(Math.random() * 100000)  );  }  

			var t1 = (new Date()).getTime();
			var arrlen1 = DelRepeatFun1(arr);     //采用indexOf 去重
			var  ms1 =  ((new Date()).getTime() -  t1);
			show("IndexOf函数去重耗时:" + ms1/1000.00 + "秒,   原数组长度: " + arr.length + ",  去重后数组长度:" + arrlen1)

			var t2= (new Date()).getTime();
			var arrlen2 = DelRepeatFun2(arr);     //采用对象属性机制去重
			var  ms2 =  ((new Date()).getTime() -  t2) ;
			show("对象属性特性去重耗时:" + ms2/1000.00 + "秒,   原数组长度: " + arr.length + ",  去重后数组长度:" + arrlen2)
			
			show("<br>性能相差<B>" +  (ms1/ms2).toFixed(2) + "</B>了倍!")
		}
		Test();  //开始执行测试

 以上是一个对20万级数组的去重,采用了2种方式去实现。

Part2. 看结果

Chrome测试结果:

IE11 测试结果:

(注:忘了注明页面编码,所以IE很智能的呈现了乱码,但实在不想运行第2遍了,太慢了,就截图标注示意一下,请原谅我的敷衍。)

 

Part3. 说原因

相同的数据,性能相差其实非常大,而且数据量级再往上提到100万级,方法2依旧不费力,但是方法1就卡住了,那原因是什么呢? 

原因就是: 

      方法1:采用的是遍历查找,  indexOf函数内部依旧是通过遍历循环查找判断是否存在,那么整个数据循环次数其实等价于  20万 * 20万 = 400亿。

 

    方法2:采用的是类似哈希查找,属性存储的机制应该采用的是类似哈希表的机制, 查找方式类似于我们常说的2分法之流(推测哈,实际上的算法应该不是我们想象中那种傻白甜的二分法), 在20万数据中用二分法锁定一个数,要多少次呢?

    2^17 = 262144 (26.2万)

   2的17次方数就超过了20万,所以理论上分17次就能在20万中锁定一个数,那么全部循环次数等于:

20万*17 = 340万

对比:   方法一循环 400亿, 方法2循环340万 , 二者理论相差: 11764 倍, 所以你说该谁快?

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值