例如:数组中有四个项目。我想随机得到一个,如下:
array items = [
"bike" //40% chance to select
"car" //30% chance to select
"boat" //15% chance to select
"train" //10% chance to select
"plane" //5% chance to select
]
答案 0 :(得分:3)
一些es6方法,使用通配符处理:
const randomizer = (values) => {
let i, pickedValue,
randomNr = Math.random(),
threshold = 0;
for (i = 0; i < values.length; i++) {
if (values[i].probability === '*') {
continue;
}
threshold += values[i].probability;
if (threshold > randomNr) {
pickedValue = values[i].value;
break;
}
if (!pickedValue) {
//nothing found based on probability value, so pick element marked with wildcard
pickedValue = values.filter((value) => value.probability === '*');
}
}
return pickedValue;
}
使用示例:
let testValues = [{
value : 'aaa',
probability: 0.1
},
{
value : 'bbb',
probability: 0.3
},
{
value : 'ccc',
probability: '*'
}]
randomizer(testValues); // will return "aaa" in 10% calls,
//"bbb" in 30% calls, and "ccc" in 60% calls;
答案 1 :(得分:1)
当然可以。这是一个简单的代码:
// Object or Array. Which every you prefer.
var item = {
bike:40, // Weighted Probability
care:30, // Weighted Probability
boat:15, // Weighted Probability
train:10, // Weighted Probability
plane:5 // Weighted Probability
// The number is not really percentage. You could put whatever number you want.
// Any number less than 1 will never occur
};
function get(input) {
var array = []; // Just Checking...
for(var item in input) {
if ( input.hasOwnProperty(item) ) { // Safety
for( var i=0; i<input[item]; i++ ) {
array.push(item);
}
}
}
// Probability Fun
return array[Math.floor(Math.random() * array.length)];
}
console.log(get(item)); // See Console.
答案 2 :(得分:0)
以上两个答案都依赖于会很快变慢的方法,尤其是公认的方法。这种数组魔术将起作用:
var items = [
"bike", //40% chance to select
"car", //30% chance to select
"boat", //15% chance to select
"train", //10% chance to select
"plane", //5% chance to select
];
var chances = [40, 30, 15, 10, 5]; //Chances of being selected
var sum = chances.reduce((acc, el) => acc + el, 0);
var acc = 0;
chances = chances.map(el => (acc = el + acc));
var rand = Math.random() * sum;
var result = items[chances.filter(el => el <= rand).length];
如果您将此设置为函数:
function chooseWeighted(items, chances) {
var sum = chances.reduce((acc, el) => acc + el, 0);
var acc = 0;
chances = chances.map(el => (acc = el + acc));
var rand = Math.random() * sum;
return items[chances.filter(el => el <= rand).length];
}
此方法快速且易于阅读。它还具有易于更改的输入的优点:您可以轻松地将其更改为接受某种对象。
答案 3 :(得分:0)
我添加了我的解决方案作为一种适用于较小数组(无缓存)的方法:
static weight_random(arr, weight_field){
if(arr == null || arr === undefined){
return null;
}
const totals = [];
let total = 0;
for(let i=0;i<arr.length;i++){
total += arr[i][weight_field];
totals.push(total);
}
const rnd = Math.floor(Math.random() * total);
let selected = arr[0];
for(let i=0;i<totals.length;i++){
if(totals[i] > rnd){
selected = arr[i];
break;
}
}
return selected;
}
像这样运行(提供数组和权重属性):
const wait_items = [
{"w" : 20, "min_ms" : "5000", "max_ms" : "10000"},
{"w" : 20, "min_ms" : "10000", "max_ms" : "20000"},
{"w" : 20, "min_ms" : "40000", "max_ms" : "80000"}
]
const item = weight_random(wait_items, "w");
console.log(item);