这是一种比其他答案建议的更快的方法......
你可以通过以下方式实现你想要的:
- 根据每个元素的概率将 0 到 1 片段划分为多个部分(例如,概率为 60% 的元素将占据片段的 60%)。
- 生成一个随机数并检查它位于哪个段。
第 1 步
为概率数组创建一个前缀和数组,其中的每个值将表示其对应部分的结束位置。
例如:
如果我们有概率:60% (0.6)、30%、5%、3%、2%。前缀和数组将为:[0.6,0.9,0.95,0.98,1]
所以我们将有一个这样划分的段(大约):[ | | ||]
第 2 步
生成一个介于 0 和 1 之间的随机数,并在前缀和数组中找到它的下限。您将找到的索引是随机数所在的段的索引
以下是实现此方法的方法:
let obj = {
"Common": "60",
"Uncommon": "25",
"Rare": "10",
"Legendary": "0.01",
"Mythical": "0.001"
}
// turning object into array and creating the prefix sum array:
let sums = [0]; // prefix sums;
let keys = [];
for(let key in obj) {
keys.push(key);
sums.push(sums[sums.length-1] + parseFloat(obj[key])/100);
}
sums.push(1);
keys.push('NONE');
// Step 2:
function lowerBound(target, low = 0, high = sums.length - 1) {
if (low == high) {
return low;
}
const midPoint = Math.floor((low + high) / 2);
if (target < sums[midPoint]) {
return lowerBound(target, low, midPoint);
} else if (target > sums[midPoint]) {
return lowerBound(target, midPoint + 1, high);
} else {
return midPoint + 1;
}
}
function getRandom() {
return lowerBound(Math.random());
}
console.log(keys[getRandom()], 'was picked!');
希望这对您有所帮助。
注意:
(在计算机科学中)列表/数组中值的下限是大于或等于它的最小元素。例如,array:[1,10,24,99] 和值 12。下限将是值为 24 的元素。
当数组从最小到最大排序时(就像我们的例子一样)找到每个值的下限可以通过二进制搜索非常快速地完成(O(log(n)))。