<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當前位置: 首頁 - 科技 - 知識百科 - 正文

        js數組實現權重概率分配

        來源:懂視網 責編:小采 時間:2020-11-27 22:30:32
        文檔

        js數組實現權重概率分配

        js數組實現權重概率分配:今天寫了一個js控制頁面輪播的功能,如果僅僅使用隊列很簡單,但是考慮到為每一個頁面分配權重的是否變的異常復雜,使用switch和if else也無法解決,于是想到使用js數組實現,思路是將各個輪播的頁面抽象成一個對象,各個對象需要手動指定權重值,然后組成一
        推薦度:
        導讀js數組實現權重概率分配:今天寫了一個js控制頁面輪播的功能,如果僅僅使用隊列很簡單,但是考慮到為每一個頁面分配權重的是否變的異常復雜,使用switch和if else也無法解決,于是想到使用js數組實現,思路是將各個輪播的頁面抽象成一個對象,各個對象需要手動指定權重值,然后組成一

        今天寫了一個js控制頁面輪播的功能,如果僅僅使用隊列很簡單,但是考慮到為每一個頁面分配權重的是否變的異常復雜,使用switch和if else也無法解決,于是想到使用js數組實現,思路是將各個輪播的頁面抽象成一個對象,各個對象需要手動指定權重值,然后組成一個數組,使用下面封裝的函數,將會根據各個對象相應的權重概率返回一個對象,代碼如下:

        /**
        * js數組實現權重概率分配
        * @param Array arr js數組,參數類型[Object,Object,Object……]
        * @return Array 返回一個隨機元素,概率為其percent/所有percent之和,參數類型Object
        * @author shuiguang
        */
        function weight_rand(arr){
         //參數arr元素必須含有percent屬性,參考如下所示
         /*
         var arr = [{
         name : '1',
         percent : 1
         }, {
         name : '2',
         percent : 2
         }, {
         name : '3',
         percent : 1
         }, {
         name : '4',
         percent : 2
         }
         ];
         */
         var total = 0;
         var i, j, percent;
         //下標標記數組,按照上面的例子,單倍情況下其組成為[1,2,2,3,4,4]
         var index = new Array();
         for (i = 0; i < arr.length; i++) {
         //判斷元素的權重,為了實現小數權重,先將所有的值放大100倍
         percent = 'undefined' != typeof(arr[i].percent) ? parseInt(arr[i].percent*100) : 0;
         for (j = 0; j < percent; j++) {
         index.push(i);
         }
         total += percent;
         }
         //隨機數值,其值介于0-5的整數
         var rand = Math.floor(Math.random() * total);
         return arr[index[rand]];
        }

        上面的方法雖然可行,可是遇到這樣一個問題:對于一般復雜的分配情況如1:1:1分配(相對值)可以滿足,如果遇到15%,25%,35%剩余等精確權重分配(絕對值)無法滿足。因為去計算15%:25%:35%:剩余的比例很是麻煩,于是我將上面的函數繼續修改,添加了百分比模式,比如上面的例子,分配了上面明確的百分數之后,剩余的百分比將給最后一個元素,而不用計算最后一個元素占的百分數,也不用計算各個元素的比例。代碼如下:

        /**
        * js數組實現權重概率分配,支持數字比模式(支持2位小數)和百分比模式(不支持小數,最后一個元素多退少補)
        * @param Array arr js數組,參數類型[Object,Object,Object……]
        * @return Array 返回一個隨機元素,概率為其weight/所有weight之和,參數類型Object
        * @author shuiguang
        */
        function weight_rand(arr){
        	//參數arr元素必須含有weight屬性,參考如下所示
        	//var arr=[{name:'1',weight:1.5},{name:'2',weight:2.5},{name:'3',weight:3.5}];
        	//var arr=[{name:'1',weight:'15%'},{name:'2',weight:'25%'},{name:'3',weight:'35%'}];
        	//求出最大公約數以計算縮小倍數,perMode為百分比模式
        	var per;
        	var maxNum = 0;
        	var perMode = false;
        	//自定義Math求最小公約數方法
        	Math.gcd = function(a,b){
        	var min = Math.min(a,b);
        	var max = Math.max(a,b);
        	var result = 1;
        	if(a === 0 || b===0){
        	return max;
        	}
        	for(var i=min; i>=1; i--){
        	if(min % i === 0 && max % i === 0){
        	result = i;
        	break;
        	}
        	}
        	return result;
        	};
        	
        	//使用clone元素對象拷貝仍然會造成浪費,但是使用權重數組對應關系更省內存
        	var weight_arr = new Array();
        	for (i = 0; i < arr.length; i++) {
        	if('undefined' != typeof(arr[i].weight))
        	{
        	if(arr[i].weight.toString().indexOf('%') !== -1) {
        	per = Math.floor(arr[i].weight.toString().replace('%',''));
        	perMode = true;
        	}else{
        	per = Math.floor(arr[i].weight*100);
        	}
        	}else{
        	per = 0;
        	}
        	weight_arr[i] = per;
        	maxNum = Math.gcd(maxNum, per);
        	}
        	//數字比模式,3:5:7,其組成[0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2]
        	//百分比模式,元素所占百分比為15%,25%,35%
        	var index = new Array();
        	var total = 0;
        	var len = 0;
        	if(perMode){
        	for (i = 0; i < arr.length; i++) {
        	//len表示存儲arr下標的數據塊長度,已優化至最小整數形式減小索引數組的長度
        	len = weight_arr[i];
        	for (j = 0; j < len; j++){
        	//超過100%跳出,后面的舍棄
        	if(total >= 100){
        	break;
        	}
        	index.push(i);
        	total++;
        	}
        	}
        	//使用最后一個元素補齊100%
        	while(total < 100){
        	index.push(arr.length-1);
        	total++;
        	}
        	}else{
        	for (i = 0; i < arr.length; i++) {
        	//len表示存儲arr下標的數據塊長度,已優化至最小整數形式減小索引數組的長度
        	len = weight_arr[i]/maxNum;
        	for (j = 0; j < len; j++){
        	index.push(i);
        	}
        	total += len;
        	}
        	}
        	//隨機數值,其值為0-11的整數,數據塊根據權重分塊
        	var rand = Math.floor(Math.random()*total);
        	//console.log(index);
        	return arr[index[rand]];
        }
        
        var arr=[{name:'1',weight:1.5},{name:'2',weight:2.5},{name:'3',weight:3.5}];
        console.log(weight_rand(arr));
        var arr=[{name:'1',weight:'15%'},{name:'2',weight:'25%'},{name:'3',weight:'35%'}];
        console.log(weight_rand(arr));
        var prize_arr = [
        	{'id':1, 'prize':'平板電腦', 'weight':1},
        	{'id':2, 'prize':'數碼相機', 'weight':2},
        	{'id':3, 'prize':'音箱設備', 'weight':10},
        	{'id':4, 'prize':'4G優盤', 'weight':12},
        	{'id':5, 'prize':'10Q幣', 'weight':22},
        	{'id':6, 'prize':'下次沒準就能中哦', 'weight':50} 
        ];
        
        var times = 100000;
        var prize;
        var pingban = 0;
        var shuma = 0;
        var yinxiang = 0;
        var youpan = 0;
        var qb = 0;
        var xc = 0;
        var start = new Date().getTime();
        
        for($i=0; $i<times; $i++){
        	prize = weight_rand(prize_arr);
        	if(prize.prize == '平板電腦')
        	{
        	pingban++;
        	}else if(prize.prize == '數碼相機'){
        	shuma++;
        	}else if(prize.prize == '音箱設備'){
        	yinxiang++;
        	}else if(prize.prize == '4G優盤'){
        	youpan++;
        	}else if(prize.prize == '10Q幣'){
        	qb++;
        	}else if(prize.prize == '下次沒準就能中哦'){
        	xc++;
        	}
        }
        
        var stop = new Date().getTime();
        console.log('平板電腦:'+pingban/times+', 數碼相機:'+shuma/times+', 音箱設備:'+yinxiang/times+', 4G優盤:'+youpan/times+', 10Q幣:'+qb/times+', 下次沒準就能中哦:'+xc/times);
        console.log('耗費時間:'+(stop-start)/1000+'秒');

        該代碼已經通過最大公約數對下標數組進行優化,使用數字比模式已經優化到最小數值比例,百分比模式考慮性能消耗暫不支持2位小數。

        寫完js版,于是很輕松改為php版本,經過10萬次循環測試,發現for循環比foreach省時間,而非網上傳的foreach比for更快。但是總體來說,js的執行速度是php的20倍左右,php的執行時間約6秒,js的執行時間約為0.346秒。

        /**
        * php數組實現權重概率分配,支持數字比模式(支持2位小數)和百分比模式(不支持小數,最后一個元素多退少補)
        * @param array $arr php數組,參數類型array(array(),array(),array()……)
        * @return array 返回一個隨機元素,概率為其percent/所有percent之和,參數類型array()
        * @author shuiguang
        */
        function weight_rand($arr)
        {
         //參數arr元素必須含有percent屬性,參考如下所示
         //$arr=array(array('name'=>'1','weight'=>1.5),array('name'=>'2','weight'=>1.5),array('name'=>'3','weight'=>1.5));
         //$arr=array(array('name'=>'1','weight'=>'15%'),array('name'=>'2','weight'=>'25%'),array('name'=>'3','weight'=>'35%'));
         //求出最大公約數以計算縮小倍數,perMode為百分比模式
         $perMode = false;
         $maxNum = 0;
         //自定義求最小公約數方法
         $gcd = function($a, $b)
         {
         $min = min($a, $b);
         $max = max($a, $b);
         $result = 1;
         if($a === 0 || $b === 0)
         {
         return $max;
         }
         for($i=$min; $i>=1; $i--)
         {
         if($min % $i === 0 && $max % $i === 0)
         {
         $result = $i;
         break;
         }
         }
         return $result;
         };
         //使用傳地址可能會影響后面的結果,但是使用權重數組對應關系更省內存
         $weight_arr = array();
         $arr_len = count($arr);
         for($i=0; $i<$arr_len; $i++)
         {
         if(isset($arr[$i]['weight']))
         {
         if(strpos($arr[$i]['weight'], '%') !== false)
         {
         $per = floor(str_replace('%', '', $arr[$i]['weight']));
         $perMode = true;
         }else{
         $per = floor($arr[$i]['weight']*100);
         }
         }else{
         $per = 0;
         }
         $weight_arr[$i] = $per;
         $maxNum = call_user_func($gcd, $maxNum, $per);
         }
         //數字比模式,3:5:7,其組成[0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2]
         //百分比模式,元素所占百分比為15%,25%,35%
         $index = array();
         $total = 0;
         if($perMode)
         {
         for($i=0; $i<$arr_len; $i++)
         {
         //$len表示存儲$arr下標的數據塊長度,已優化至最小整數形式減小索引數組的長度
         $len = $weight_arr[$i];
         for ($j = 0; $j < $len; $j++)
         {
         //超過100%跳出,后面的舍棄
         if($total >= 100)
         {
         break;
         }
         $index[] = $i;
         $total++;
         }
         }
         //使用最后一個元素補齊100%
         while($total < 100)
         {
         $index[] = $arr_len-1;
         $total++;
         }
         }else{
         for($i=0; $i<$arr_len; $i++)
         {
         //len表示存儲arr下標的數據塊長度,已優化至最小整數形式減小索引數組的長度
         $len = $weight_arr[$i]/$maxNum;
         for ($j = 0; $j < $len; $j++)
         {
         $index[] = $i;
         }
         $total += $len;
         }
         }
         //隨機數值,其值為0-11的整數,數據塊根據權重分塊
         $rand = floor(mt_rand(0, $total));
        	//修復php隨機函數可以取臨界值造成的bug
         $rand = $rand == $total ? $total-1 : $rand;
         return $arr[$index[$rand]];
        }
        
        $arr=array(array('name'=>'1','weight'=>1.5),array('name'=>'2','weight'=>1.5),array('name'=>'3','weight'=>1.5));
        p(weight_rand($arr));
        $arr=array(array('name'=>'1','weight'=>'15%'),array('name'=>'2','weight'=>'25%'),array('name'=>'3','weight'=>'35%'));
        p(weight_rand($arr));
        
        $prize_arr = array(
        	'0' => array('id'=>1, 'prize'=>'平板電腦', 'weight'=>1),
        	'1' => array('id'=>2, 'prize'=>'數碼相機', 'weight'=>5),
        	'2' => array('id'=>3, 'prize'=>'音箱設備', 'weight'=>10),
        	'3' => array('id'=>4, 'prize'=>'4G優盤', 'weight'=>12),
        	'4' => array('id'=>5, 'prize'=>'10Q幣', 'weight'=>22),
        	'5' => array('id'=>6, 'prize'=>'下次沒準就能中哦', 'weight'=>50),
        );
        
        $start = time();
        $result = array();
        $times = 100000;
        for($i=0; $i<$times; $i++)
        {
        	$row = weight_rand($prize_arr);
        	if(array_key_exists($row['prize'], $result))
        	{
        	$result[$row['prize']] ++;
        	}else{
        	$result[$row['prize']] = 1;
        	}
        }
        $cost = time() - $start;
        
        
        p($result);
        p('耗費時間:'.$cost.'秒');
        function p($var)
        {
         echo "<pre>";
         if($var === false)
         {
         echo 'false';
         }else if($var === ''){
         print_r("''");
         }else{
         print_r($var);
         }
         echo "</pre>";
        }

        php版本如果只是使用整數數字比模式,完全不用考慮數字的放大與求最小公倍數的算法,只需要做簡單的累加即可,可以大大縮短執行時間。

        聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        js數組實現權重概率分配

        js數組實現權重概率分配:今天寫了一個js控制頁面輪播的功能,如果僅僅使用隊列很簡單,但是考慮到為每一個頁面分配權重的是否變的異常復雜,使用switch和if else也無法解決,于是想到使用js數組實現,思路是將各個輪播的頁面抽象成一個對象,各個對象需要手動指定權重值,然后組成一
        推薦度:
        標簽: 實現 js 權重
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 国产精品免费无遮挡无码永久视频 | 亚洲A∨无码一区二区三区| 亚洲精品中文字幕| 日本成年免费网站| 亚洲欧洲日本国产| 日本红怡院亚洲红怡院最新| 亚洲av无码无在线观看红杏| 亚洲13又紧又嫩又水多| 精品无码国产污污污免费网站 | 亚洲AV伊人久久青青草原| 国产AV日韩A∨亚洲AV电影| 久久黄色免费网站| 久久青青草原亚洲AV无码麻豆| 中文在线免费视频| 日韩一级免费视频| 亚洲av日韩av永久无码电影 | 欧洲精品免费一区二区三区| 在线亚洲午夜理论AV大片| 一级毛片成人免费看a| 日本zzzzwww大片免费| 精品亚洲一区二区三区在线播放| 男人j进女人p免费视频| 好吊妞在线新免费视频| 亚洲av午夜国产精品无码中文字 | 亚洲国产精品美女| 成人a视频片在线观看免费| 亚洲youwu永久无码精品| 国产青草视频免费观看97| 日本一区二区三区免费高清在线| 国产亚洲精品不卡在线| 美丽姑娘免费观看在线观看中文版| 在线免费视频一区二区| 阿v免费在线观看| 中文字幕亚洲专区| 99在线在线视频免费视频观看| 亚洲一级黄色大片| 国产国拍亚洲精品福利| 四虎在线最新永久免费| 无人视频免费观看免费视频| 亚洲AV无码码潮喷在线观看 | 天堂亚洲免费视频|