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;