ホームページ  >  記事  >  ウェブフロントエンド  >  js配列で重み確率ソートを実装する方法

js配列で重み確率ソートを実装する方法

php中世界最好的语言
php中世界最好的语言オリジナル
2018-04-17 11:54:222270ブラウズ

今回は、js 配列の重み確率ソートを実装する方法を説明します。js 配列の重み確率ソートを実装するための 注意事項 は何ですか? ここで実際のケースを見てみましょう。

今日はページカルーセルを制御するjs関数を書きました。キューを使うだけならとても簡単ですが、各ページの重み付けが非常に複雑になることを考慮してswitchとifを使います。 それ以外の場合は解決できないため、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 = &#39;undefined&#39; != 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:&#39;1&#39;,weight:1.5},{name:&#39;2&#39;,weight:2.5},{name:&#39;3&#39;,weight:3.5}];
	//var arr=[{name:&#39;1&#39;,weight:&#39;15%&#39;},{name:&#39;2&#39;,weight:&#39;25%&#39;},{name:&#39;3&#39;,weight:&#39;35%&#39;}];
	//求出最大公约数以计算缩小倍数,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(&#39;undefined&#39; != typeof(arr[i].weight))
		{
			if(arr[i].weight.toString().indexOf(&#39;%&#39;) !== -1) {
				per = Math.floor(arr[i].weight.toString().replace(&#39;%&#39;,&#39;&#39;));
				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 バージョンに変更しました。100,000 回のループ テストの後、

for ループforeach よりも時間を節約でき、オンラインにアップロードされていない foreach は for よりも高速であることがわかりました。ただし、一般的にjsの実行速度はphpの約20倍で、phpの実行時間は約6秒、jsの実行時間は約0.346秒です。 りー

PHP バージョンが整数比モードのみを使用する場合は、数値の増幅や最小公倍数を求めるアルゴリズムを考慮する必要がなく、単純な累積を行うだけでよいため、実行時間を大幅に短縮できます。

この記事の事例を読んだ後は、この方法を習得したと思います。さらに興味深い情報については、php 中国語 Web サイトの他の関連記事に注目してください。

推奨読書:

3 つのマウス クリック イベントのバインド

ブラウザーの Date() 関数の互換性問題の処理


以上がjs配列で重み確率ソートを実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。