zoukankan      html  css  js  c++  java
  • 如何提高数组循环的效率 倒序循环、Duff`s Device、异步迭代

    >倒序循环可以略微的提升普通迭代的性能,如下:

    	/*
    	 * 一种可以提高循环效率的方法,倒序遍历,同步模式
    	 */
    	var reverseFor   = function(arr, handler){
    		for(var i = arr.length; i --;){
    			// 传入三个参数,当前数组项的值,索引,原始数组
    			handler(arr[i], i, arr);
    		}
    	};

    >Duff`s Device迭代优化算法着重减少总工作量的迭代次数,如下(非原创,但已修复):

    	/*
    	 * Duff's Device 经典实现,同步模式,目的是减少迭代次数
    	 */
    	var duffDevFor        = function(arr, handler){
    		var length     = arr.length;
    		// 下舍入
    		var times      = Math.ceil(length / 8),
    			start      = length % 8,
    			inx        = 0;
    
    		do{
    			switch(start){
    				case 0 : handler(arr[inx ++], inx - 1, arr);
    				case 7 : handler(arr[inx ++], inx - 1, arr);
    				case 6 : handler(arr[inx ++], inx - 1, arr);
    				case 5 : handler(arr[inx ++], inx - 1, arr);
    				case 4 : handler(arr[inx ++], inx - 1, arr);
    				case 3 : handler(arr[inx ++], inx - 1, arr);
    				case 2 : handler(arr[inx ++], inx - 1, arr);
    				case 1 : handler(arr[inx ++], inx - 1, arr);
    			}
    			start = 0;//归位
    		}while(-- times)
    	};

    但是上面的实现是最初的实现,还可以通过去掉switch语句来进一步提升效率:

    	/*
    	 * 优化后的 Duff's Device,同步模式,目的是减少迭代次数
    	 */
    	var duffDevBetFor    = function(arr, handler){
    		var length    = arr.length;
    		var inx       = 0;
    		// 余数循环
    		var remainder = length % 8;
    		while(remainder){
    			handler(arr[inx ++], inx - 1, arr);
    			remainder --;
    		}
    		// 主循环
    		var times     = Math.floor(length / 8);
    		while(times){
    			handler(arr[inx ++], inx - 1, arr);
    			handler(arr[inx ++], inx - 1, arr);
    			handler(arr[inx ++], inx - 1, arr);
    			handler(arr[inx ++], inx - 1, arr);
    			handler(arr[inx ++], inx - 1, arr);
    			handler(arr[inx ++], inx - 1, arr);
    			handler(arr[inx ++], inx - 1, arr);
    			handler(arr[inx ++], inx - 1, arr);
    			times --;
    		}
    	};

    >异步迭代:

    	/**
    	 * 异步迭代器
    	 * 
    	 * @param {Object} opt
    	 *
    	 * @param {Number} opt.from 起始数字
    	 * @param {Number} opt.to 结束数字(可正可负,为负的时候,step相应的也是复数)
    	 * @param {Number} opt.step 每一次迭代的步子大小
    	 * @param {Number} opt.iterate 在每一次interval之中,迭代多少次,默认是1次
    	 * @param {Number} opt.interval 时间间隔,毫秒记
    	 * @param {Function} opt.stepCallback 每一此迭代处理的调用函数,会传入每次迭代的index
    	 * @param {Function} opt.finalCallBack 全部结束后的回调函数,传入最后一次迭代的index
    	 */
    	var asyncFor = function(
    		/*{from : , to : , step : , iterate : , interval : , stepCallback : , finalCallBack : }*/
    		opt
    	){
    		var from      = opt.from,
    			to        = opt.to,
    			iterate   = opt.iterate || 1,
    			positive  = opt.step > 0,
    			over      = false;
    			beStop    = function(){
    				// 等于-1的时候,条件不满足
    				return positive ? (
    					from == to ? 1 : from > to ? 0 : -1
    				) : (
    					from == to ? 1 : from < to ? 0 : -1
    				);
    			};
    		// 第一次调用
    		main();
    		var timer = window.setInterval(function(){
    			main();
    		}, opt.interval);
    		// 主循环体
    		function main(){
    			// 如果第一次调用main就已经全部执行完的话,在下次清除timer
    			if(over){
    				window.clearInterval(timer);
    				return;
    			}
    			while(iterate){
    				var temp  = beStop();
    				if(!(temp == -1)){
    					// 结束条件满足
    					window.clearInterval(timer);
    					// 如果from == to,需要调用一次stepCallback
    					if(temp == 1)
    						if(opt.stepCallback)
    							opt.stepCallback(from);
    					if(opt.finalCallBack)
    						opt.finalCallBack(
    							temp == 0 ? (from -= opt.step) : from
    						);
    					over = true;
    					// 跳出循环
    					break;
    				}
    				if(opt.stepCallback)
    					opt.stepCallback(from);
    				from += opt.step;
    				iterate --;
    			}
    			// 归位
    			iterate = opt.iterate || 1;
    		};
    	};

    那么如何使用呢?

    	asyncFor({
    		from: 1,
    		to: 300,
    		step: 2,
    		interval: 10,
    		iterate: 10,
    		stepCallback: function(inx){
    			console.log(inx);
    		},
    		finalCallBack: function(finalIndex){
    			console.log(finalIndex + '-End Index.');
    		}
    	});

    作为常用的工具函数   -  -



  • 相关阅读:
    【K8S】Kubernetes: --image-pull-policy always does not work
    【Maven插件】exec-maven-plugin
    【分布式事务】微服务架构下的分布式事务问题
    【Jenkins】新版本的特性:自定义流水线
    【Kibana】自定义contextPath
    【Zuul】Zuul过滤器参考资料
    【Spring】Springboot监听器,启动之后初始化工作
    【Spring】bean动态注册到spring
    【Java-JPA】让Springboot启动不检查JPA的数据源配置
    linux-批量杀死进程
  • 原文地址:https://www.cnblogs.com/catprayer/p/2699051.html
Copyright © 2011-2022 走看看