javascript - 以概率随机播放 JS 数组
问题描述
假设我有一个这样的数组:
const alphabet = ['a', 'b', 'c', 'd'];
这代表 4 个政治候选人和一个等级选择投票,其中候选人a
是第一选择,b
是第二选择,等等。
我想把它打乱成一堆随机顺序,但在这种情况下,我想a
首先出现可能有 60%,b
第二个出现概率为 20%,c
第三个出现概率为 10%,所有其他排序可能有 10%。是否有一些 lodash 和 ramda 功能可以做到这一点?
这是为了测试等级选择投票算法。随机改组数组会产生具有几乎相同投票数的候选人,这并不反映大多数现实(尽管我也会对此进行测试)。
我有一个非常可怕的例程,它将生成一个随机数组:
const getValues = function () {
const results = [];
const remaining = new Set(alphabet);
const probabilities = [0.6, 0.2, 0.1, 0.1];
for(let i = 0; i < alphabet.length; i++){
const r = Math.random();
const letter = alphabet[i];
if(r < probabilities[i] && remaining.has(letter)){
results.push(letter);
remaining.delete(letter);
}
else{
const rand = Math.floor(Math.random()*remaining.size);
const x = Array.from(remaining)[rand];
remaining.delete(x);
results.push(x);
}
}
return results;
};
这“有效”,但由于条件概率,它并没有根据指定的概率对事物进行排序。如上所述,有人知道以一定概率出现订单的好方法吗?
这是我正在寻找的一些示例输出:
[ [ 'd', 'b', 'a', 'c' ],
[ 'a', 'b', 'c', 'd' ],
[ 'a', 'd', 'b', 'c' ],
[ 'd', 'b', 'a', 'c' ],
[ 'b', 'c', 'a', 'd' ],
[ 'a', 'b', 'c', 'd' ],
[ 'd', 'b', 'c', 'a' ],
[ 'c', 'd', 'a', 'b' ],
[ 'd', 'b', 'a', 'c' ],
[ 'a', 'b', 'c', 'd' ] ]
如果您生成了足够的数据,它将不符合所需的顺序/分布。
解决方案
您可以随机抽取数组的一部分并对剩余的可能性进行归一化,然后再抽取一个,直到所有项目都被取走。
结果,您几乎得到了想要的结果,正如您在counts
项目及其最终索引中看到的那样。
const
getIndex = (prob) => prob.findIndex((r => p => r < p || (r -= p, false))(Math.random())),
normalized = array => {
var sum = array.reduce((a, b) => a + b, 0);
return array.map(v => v / sum);
};
var items = ['a', 'b', 'c', 'd'],
probabilities = [0.6, 0.2, 0.1, 0.1],
counts = { a: { 0: 0, 1: 0, 2: 0, 3: 0 }, b: { 0: 0, 1: 0, 2: 0, 3: 0 }, c: { 0: 0, 1: 0, 2: 0, 3: 0 }, d: { 0: 0, 1: 0, 2: 0, 3: 0 } },
l = 100,
index,
result = [],
subP,
subI,
temp;
while (l--) {
temp = [];
subP = probabilities.slice();
subI = items.slice();
while (subP.length) {
sum = subP.reduce
index = getIndex(normalized(subP));
temp.push(subI[index]);
subI.splice(index, 1);
subP.splice(index, 1);
}
result.push(temp);
}
console.log(result.map(a => a.join()));
result.forEach(a => a.forEach((v, i) => counts[v][i]++));
console.log(counts);
.as-console-wrapper { max-height: 100% !important; top: 0; }
推荐阅读
- php - 无法将文件上传到 oboom.com API
- go - 使用 golang 实现四叉树的递归并发
- css - 以 80% 宽度为中心的固定位置标题 Div
- php - 使用多个模型和集合 - Laravel
- angular - Firefox 上的 Angular 6 [WDS] 断开连接错误
- c# - 使用 CrossSimpleAudioPlayer 播放声音 - Xamarin Forms
- excel - 过滤多个工作表(同一工作簿)中的数据并复制另一个工作簿工作表中的数据
- javascript - AngularJS 1.5 组件将数据绑定到控制器并使用模板 url 进行视图
- c# - 未检测到 Visual Studio 2017 中的新类项
- python - Scrapy 解析重定向优先