**例如:**数组中有四个元素。我想随机得到一个,像这样:
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
]
**例如:**数组中有四个元素。我想随机得到一个,像这样:
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
]
8条答案
按热度按时间kknvjkwl1#
上面的两个答案都依赖于很快变慢的方法,尤其是被公认的方法。
截至2020年12月,我用这个解决方案取代了我的旧ES6解决方案,因为旧浏览器不支持ES6,我个人认为这个解决方案更具可读性。
如果您更愿意使用具有属性
item
和weight
的对象:说明:
我做了这个图表来说明它是如何工作的:
该图显示了当给定权重为
[5, 2, 8, 3]
的输入时会发生什么。通过取权重的部分和,你只需要找到第一个和随机数一样大的,那就是随机选择的项目。如果在两个权重的边界上选择一个随机数,如图中的
7
和15
,我们选择较长的一个。这是因为0
可以被Math.random
选择,而1
不能,所以我们得到了一个公平的分布。如果我们使用较短的一个,A
可以在18次中选择6次(0
,1
,2
,3
,4
),使其具有比应有的更高的权重。mrzz3bfm2#
一些es6方法,带通配符处理:
用法示例:
zpgglvta3#
这里有一个更快的方法,然后其他答案建议。..
你可以通过以下方式实现你想要的:
1.基于每个元素的概率将0到1的段划分为每个元素的部分(例如,概率为60%的元素将占据段的60%)。
1.生成随机数并检查它落在哪个段中。
第一步
为概率数组做一个前缀和数组,其中的每个值将表示其对应部分的结束位置。
例如:如果我们有概率:60%(0.6)、30%、5%、3%、2%。前缀和数组将是:
[0.6,0.9,0.95,0.98,1]
我们将有一个这样的分段(近似):
[ | | ||]
步骤2
在0和1之间生成一个随机数,并在前缀和数组中找到它的下界。你将找到的索引是随机数所在的段的索引
下面是如何实现此方法:
希望这对你有帮助。注意:(在计算机科学中)列表/数组中值的下限是大于或等于它的最小元素。例如,array:
[1,10,24,99]
和值12。下限将是具有值24的元素。当数组从最小到最大排序时(就像在我们的例子中),找到每个值的下限可以非常快地通过二进制搜索(O(log(n)))完成。oprakyz74#
这里有一个O(1)(常数时间)算法来解决你的问题。
生成一个从0到99的随机数(总共100个数字)。如果在给定的子范围内有40个数字(0到39),那么随机选择的数字将有40%的概率落在这个范围内。代码如下:
还记得这个吗,一个小学的数学原理?“一个特定分布中的所有数字都有相等的概率被随机选择。”
这告诉我们,每个随机数在特定范围内出现的概率相等,无论该范围有多大或小。
就这样。应该可以了!
cdmah0mi5#
我添加了我的解决方案,作为一个在较小数组上工作良好的方法(没有缓存):
像这样运行它(提供数组和权重属性):
ltqd579y6#
ES2015版本Radvylf Programs's answer
ES2022
yxyvkwin7#
我最近遇到了这个问题,并使用switch case解决了它,这很有帮助,因为您可以为每个元素分配多个“case”,从而对它们进行加权。
我有一个简单的,常见的随机数函数,我运行它的随机性:
您可以随意更改这些值,但要点是开关从1到10滚动一个随机数,并且情况确定el 3有10%的机会(1/10),el 2有20%的机会,并且对于情况1-7,el 1是赢家(70%)。
如果你想在一个更大的数组中加权一个数组元素的范围,你可以让case运行另一个随机数来从 range 中挑选,而不是返回一个固定的元素。即
gkn4icbw8#
你当然可以这里有一个简单的代码来做这件事: