• <fieldset id="8imwq"><menu id="8imwq"></menu></fieldset>
  • <bdo id="8imwq"><input id="8imwq"></input></bdo>
    最新文章專題視頻專題問(wèn)答1問(wèn)答10問(wèn)答100問(wèn)答1000問(wèn)答2000關(guān)鍵字專題1關(guān)鍵字專題50關(guān)鍵字專題500關(guān)鍵字專題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關(guān)鍵字專題關(guān)鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
    問(wèn)答文章1 問(wèn)答文章501 問(wèn)答文章1001 問(wèn)答文章1501 問(wèn)答文章2001 問(wèn)答文章2501 問(wèn)答文章3001 問(wèn)答文章3501 問(wèn)答文章4001 問(wèn)答文章4501 問(wèn)答文章5001 問(wèn)答文章5501 問(wèn)答文章6001 問(wèn)答文章6501 問(wèn)答文章7001 問(wèn)答文章7501 問(wèn)答文章8001 問(wèn)答文章8501 問(wèn)答文章9001 問(wèn)答文章9501
    當(dāng)前位置: 首頁(yè) - 科技 - 知識(shí)百科 - 正文

    js數(shù)組實(shí)現(xiàn)權(quán)重概率分配

    來(lái)源:懂視網(wǎng) 責(zé)編:小采 時(shí)間:2020-11-27 22:30:32
    文檔

    js數(shù)組實(shí)現(xiàn)權(quán)重概率分配

    js數(shù)組實(shí)現(xiàn)權(quán)重概率分配:今天寫了一個(gè)js控制頁(yè)面輪播的功能,如果僅僅使用隊(duì)列很簡(jiǎn)單,但是考慮到為每一個(gè)頁(yè)面分配權(quán)重的是否變的異常復(fù)雜,使用switch和if else也無(wú)法解決,于是想到使用js數(shù)組實(shí)現(xiàn),思路是將各個(gè)輪播的頁(yè)面抽象成一個(gè)對(duì)象,各個(gè)對(duì)象需要手動(dòng)指定權(quán)重值,然后組成一
    推薦度:
    導(dǎo)讀js數(shù)組實(shí)現(xiàn)權(quán)重概率分配:今天寫了一個(gè)js控制頁(yè)面輪播的功能,如果僅僅使用隊(duì)列很簡(jiǎn)單,但是考慮到為每一個(gè)頁(yè)面分配權(quán)重的是否變的異常復(fù)雜,使用switch和if else也無(wú)法解決,于是想到使用js數(shù)組實(shí)現(xiàn),思路是將各個(gè)輪播的頁(yè)面抽象成一個(gè)對(duì)象,各個(gè)對(duì)象需要手動(dòng)指定權(quán)重值,然后組成一

    今天寫了一個(gè)js控制頁(yè)面輪播的功能,如果僅僅使用隊(duì)列很簡(jiǎn)單,但是考慮到為每一個(gè)頁(yè)面分配權(quán)重的是否變的異常復(fù)雜,使用switch和if else也無(wú)法解決,于是想到使用js數(shù)組實(shí)現(xiàn),思路是將各個(gè)輪播的頁(yè)面抽象成一個(gè)對(duì)象,各個(gè)對(duì)象需要手動(dòng)指定權(quán)重值,然后組成一個(gè)數(shù)組,使用下面封裝的函數(shù),將會(huì)根據(jù)各個(gè)對(duì)象相應(yīng)的權(quán)重概率返回一個(gè)對(duì)象,代碼如下:

    /**
    * js數(shù)組實(shí)現(xiàn)權(quán)重概率分配
    * @param Array arr js數(shù)組,參數(shù)類型[Object,Object,Object……]
    * @return Array 返回一個(gè)隨機(jī)元素,概率為其percent/所有percent之和,參數(shù)類型Object
    * @author shuiguang
    */
    function weight_rand(arr){
     //參數(shù)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;
     //下標(biāo)標(biāo)記數(shù)組,按照上面的例子,單倍情況下其組成為[1,2,2,3,4,4]
     var index = new Array();
     for (i = 0; i < arr.length; i++) {
     //判斷元素的權(quán)重,為了實(shí)現(xiàn)小數(shù)權(quán)重,先將所有的值放大100倍
     percent = 'undefined' != typeof(arr[i].percent) ? parseInt(arr[i].percent*100) : 0;
     for (j = 0; j < percent; j++) {
     index.push(i);
     }
     total += percent;
     }
     //隨機(jī)數(shù)值,其值介于0-5的整數(shù)
     var rand = Math.floor(Math.random() * total);
     return arr[index[rand]];
    }

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

    /**
    * js數(shù)組實(shí)現(xiàn)權(quán)重概率分配,支持?jǐn)?shù)字比模式(支持2位小數(shù))和百分比模式(不支持小數(shù),最后一個(gè)元素多退少補(bǔ))
    * @param Array arr js數(shù)組,參數(shù)類型[Object,Object,Object……]
    * @return Array 返回一個(gè)隨機(jī)元素,概率為其weight/所有weight之和,參數(shù)類型Object
    * @author shuiguang
    */
    function weight_rand(arr){
    	//參數(shù)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%'}];
    	//求出最大公約數(shù)以計(jì)算縮小倍數(shù),perMode為百分比模式
    	var per;
    	var maxNum = 0;
    	var perMode = false;
    	//自定義Math求最小公約數(shù)方法
    	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元素對(duì)象拷貝仍然會(huì)造成浪費(fèi),但是使用權(quán)重?cái)?shù)組對(duì)應(yīng)關(guān)系更省內(nèi)存
    	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);
    	}
    	//數(shù)字比模式,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表示存儲(chǔ)arr下標(biāo)的數(shù)據(jù)塊長(zhǎng)度,已優(yōu)化至最小整數(shù)形式減小索引數(shù)組的長(zhǎng)度
    	len = weight_arr[i];
    	for (j = 0; j < len; j++){
    	//超過(guò)100%跳出,后面的舍棄
    	if(total >= 100){
    	break;
    	}
    	index.push(i);
    	total++;
    	}
    	}
    	//使用最后一個(gè)元素補(bǔ)齊100%
    	while(total < 100){
    	index.push(arr.length-1);
    	total++;
    	}
    	}else{
    	for (i = 0; i < arr.length; i++) {
    	//len表示存儲(chǔ)arr下標(biāo)的數(shù)據(jù)塊長(zhǎng)度,已優(yōu)化至最小整數(shù)形式減小索引數(shù)組的長(zhǎng)度
    	len = weight_arr[i]/maxNum;
    	for (j = 0; j < len; j++){
    	index.push(i);
    	}
    	total += len;
    	}
    	}
    	//隨機(jī)數(shù)值,其值為0-11的整數(shù),數(shù)據(jù)塊根據(jù)權(quán)重分塊
    	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':'數(shù)碼相機(jī)', 'weight':2},
    	{'id':3, 'prize':'音箱設(shè)備', 'weight':10},
    	{'id':4, 'prize':'4G優(yōu)盤', 'weight':12},
    	{'id':5, 'prize':'10Q幣', 'weight':22},
    	{'id':6, 'prize':'下次沒(méi)準(zhǔn)就能中哦', '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 == '數(shù)碼相機(jī)'){
    	shuma++;
    	}else if(prize.prize == '音箱設(shè)備'){
    	yinxiang++;
    	}else if(prize.prize == '4G優(yōu)盤'){
    	youpan++;
    	}else if(prize.prize == '10Q幣'){
    	qb++;
    	}else if(prize.prize == '下次沒(méi)準(zhǔn)就能中哦'){
    	xc++;
    	}
    }
    
    var stop = new Date().getTime();
    console.log('平板電腦:'+pingban/times+', 數(shù)碼相機(jī):'+shuma/times+', 音箱設(shè)備:'+yinxiang/times+', 4G優(yōu)盤:'+youpan/times+', 10Q幣:'+qb/times+', 下次沒(méi)準(zhǔn)就能中哦:'+xc/times);
    console.log('耗費(fèi)時(shí)間:'+(stop-start)/1000+'秒');

    該代碼已經(jīng)通過(guò)最大公約數(shù)對(duì)下標(biāo)數(shù)組進(jìn)行優(yōu)化,使用數(shù)字比模式已經(jīng)優(yōu)化到最小數(shù)值比例,百分比模式考慮性能消耗暫不支持2位小數(shù)。

    寫完js版,于是很輕松改為php版本,經(jīng)過(guò)10萬(wàn)次循環(huán)測(cè)試,發(fā)現(xiàn)for循環(huán)比f(wàn)oreach省時(shí)間,而非網(wǎng)上傳的foreach比f(wàn)or更快。但是總體來(lái)說(shuō),js的執(zhí)行速度是php的20倍左右,php的執(zhí)行時(shí)間約6秒,js的執(zhí)行時(shí)間約為0.346秒。

    /**
    * php數(shù)組實(shí)現(xiàn)權(quán)重概率分配,支持?jǐn)?shù)字比模式(支持2位小數(shù))和百分比模式(不支持小數(shù),最后一個(gè)元素多退少補(bǔ))
    * @param array $arr php數(shù)組,參數(shù)類型array(array(),array(),array()……)
    * @return array 返回一個(gè)隨機(jī)元素,概率為其percent/所有percent之和,參數(shù)類型array()
    * @author shuiguang
    */
    function weight_rand($arr)
    {
     //參數(shù)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%'));
     //求出最大公約數(shù)以計(jì)算縮小倍數(shù),perMode為百分比模式
     $perMode = false;
     $maxNum = 0;
     //自定義求最小公約數(shù)方法
     $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;
     };
     //使用傳地址可能會(huì)影響后面的結(jié)果,但是使用權(quán)重?cái)?shù)組對(duì)應(yīng)關(guān)系更省內(nèi)存
     $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);
     }
     //數(shù)字比模式,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表示存儲(chǔ)$arr下標(biāo)的數(shù)據(jù)塊長(zhǎng)度,已優(yōu)化至最小整數(shù)形式減小索引數(shù)組的長(zhǎng)度
     $len = $weight_arr[$i];
     for ($j = 0; $j < $len; $j++)
     {
     //超過(guò)100%跳出,后面的舍棄
     if($total >= 100)
     {
     break;
     }
     $index[] = $i;
     $total++;
     }
     }
     //使用最后一個(gè)元素補(bǔ)齊100%
     while($total < 100)
     {
     $index[] = $arr_len-1;
     $total++;
     }
     }else{
     for($i=0; $i<$arr_len; $i++)
     {
     //len表示存儲(chǔ)arr下標(biāo)的數(shù)據(jù)塊長(zhǎng)度,已優(yōu)化至最小整數(shù)形式減小索引數(shù)組的長(zhǎng)度
     $len = $weight_arr[$i]/$maxNum;
     for ($j = 0; $j < $len; $j++)
     {
     $index[] = $i;
     }
     $total += $len;
     }
     }
     //隨機(jī)數(shù)值,其值為0-11的整數(shù),數(shù)據(jù)塊根據(jù)權(quán)重分塊
     $rand = floor(mt_rand(0, $total));
    	//修復(fù)php隨機(jī)函數(shù)可以取臨界值造成的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'=>'數(shù)碼相機(jī)', 'weight'=>5),
    	'2' => array('id'=>3, 'prize'=>'音箱設(shè)備', 'weight'=>10),
    	'3' => array('id'=>4, 'prize'=>'4G優(yōu)盤', 'weight'=>12),
    	'4' => array('id'=>5, 'prize'=>'10Q幣', 'weight'=>22),
    	'5' => array('id'=>6, 'prize'=>'下次沒(méi)準(zhǔn)就能中哦', '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('耗費(fèi)時(shí)間:'.$cost.'秒');
    function p($var)
    {
     echo "<pre>";
     if($var === false)
     {
     echo 'false';
     }else if($var === ''){
     print_r("''");
     }else{
     print_r($var);
     }
     echo "</pre>";
    }

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

    聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

    文檔

    js數(shù)組實(shí)現(xiàn)權(quán)重概率分配

    js數(shù)組實(shí)現(xiàn)權(quán)重概率分配:今天寫了一個(gè)js控制頁(yè)面輪播的功能,如果僅僅使用隊(duì)列很簡(jiǎn)單,但是考慮到為每一個(gè)頁(yè)面分配權(quán)重的是否變的異常復(fù)雜,使用switch和if else也無(wú)法解決,于是想到使用js數(shù)組實(shí)現(xiàn),思路是將各個(gè)輪播的頁(yè)面抽象成一個(gè)對(duì)象,各個(gè)對(duì)象需要手動(dòng)指定權(quán)重值,然后組成一
    推薦度:
    • 熱門焦點(diǎn)

    最新推薦

    猜你喜歡

    熱門推薦

    專題
    Top
    主站蜘蛛池模板: 少妇人妻精品一区二区三区| 亚洲综合国产精品| 国产成人久久精品一区二区三区| 惠民福利中文字幕人妻无码乱精品 | 国产精品第一区第27页| 亚洲人成精品久久久久| 国产成人99久久亚洲综合精品| 国产精品一久久香蕉国产线看观看| 亚洲国产av无码精品| 狠狠精品干练久久久无码中文字幕 | 国内精品伊人久久久久AV影院| 污污网站国产精品白丝袜| 国产2021久久精品| 久久精品无码一区二区三区| 精品久久人妻av中文字幕| 在线涩涩免费观看国产精品| 日韩AV毛片精品久久久| 国产精品无码不卡一区二区三区| 青青青青久久精品国产h| 国产福利91精品一区二区三区| 精品蜜臀久久久久99网站| 人人妻人人澡人人爽人人精品97 | 精品一区二区三区色花堂| 91人妻人人澡人人爽人人精品| 精品在线免费观看| 国产成人亚洲合集青青草原精品| 99精品一区二区三区无码吞精| 精品熟女少妇av免费久久| 青草国产精品久久久久久| 老司机亚洲精品影院无码| 亚洲av无码乱码国产精品| 色婷婷在线精品国自产拍| 无码人妻精品中文字幕| 日产精品一线二线三线芒果| 嫩草伊人久久精品少妇AV| 人妻精品久久无码区| 精品人伦一区二区三区潘金莲| 国产女主播精品大秀系列| 97久久久精品综合88久久| 国产精品久久久久久搜索| 久久99精品国产一区二区三区|