我似乎无法找到一种有效的方法来按每个对象的百分比选择一个随机对象。
基本上,我给方法一个对象的地图,并有机会挑选该对象。我最好想要它,因为它可以有很多小数,因为最长的小数,但1小数也可以。
public static <T> T random(Map<T, Double> chances) {
T toReturn = null;
double rand = new Random().nextInt(1000) / 10.0D;
// ???
return toReturn;
}
提前致谢。
答案 0 :(得分:2)
基本策略:
答案 1 :(得分:1)
如果每个对象都映射到一个概率(大概增加到100),那么你别无选择,只能迭代它们:
public static <T> T getRandomItem(Map<T, Double> chances) {
double chance = random.nextDouble() * 100.0;
double cumulative = 0.0;
for (T item: chances.keySet()) {
cumulative += chances.get(item);
if (chance < cumulative)
return item;
}
throw new IllegalStateException("chances don't sum to 100");
}
答案 2 :(得分:1)
此问题称为“健身比例选择”,您无法在wikipedia上找到更多信息(和示例代码)。
答案 3 :(得分:0)
在这种情况下,我会使用具有累积机会的列表。假设你有五个物体的机率分别为0.1,0.3,0.2,0.1,0.3。然后我会创建一个新的数组A,其值为A = [0.1,0.4,0.6,0.7,1.0],即如果n> 0且A [0] = A [n] = A [n-1] + p_n p_0其中p_n是对象n的可能性。然后你可以创建一个随机数r并在A中找到最高元素x,使得A [x]> r,并且x是你想要的对象的索引。
伪:
cumulative_chances = [chances[0]]
for i=1 to chances.size()
cumulative_chances.append(chances[i]+cumulative_chances[i-1])
r=random(0, cumulative_chances.last())
i=0
while cumulative_chances[i]<r
i++
return i
请注意,我假设所有n的p_n> 0。如果您想将任何项目的概率设置为零,则必须稍微修改它。
如果应用程序中没有任何内容对性能敏感,则可以在函数内部进行此计算。在其他情况下,我会预先计算它。请注意,伪代码对值的规范化不敏感。他们不需要将upp添加到1(如果你想要百分比,则需要100),无论如何都可以。
答案 4 :(得分:0)
我做了Patrick Parker告诉我的事情,这很完美!非常感谢。
(<!! rand-int-chan)
; nil