如何在 Javascript 中选择加权随机数组元素?

新手上路,请多包涵

例如: 数组中有四个项目。我想随机得到一个,像这样:

 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
]

原文由 Geza 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 773
2 个回答

你当然可以。这是一个简单的代码:

     // 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.

原文由 Noobit 发布,翻译遵循 CC BY-SA 3.0 许可协议

上面的两个答案都依赖于会很快变慢的方法,尤其是公认的方法。

 function weighted_random(items, weights) {
    var i;

    for (i = 0; i < weights.length; i++)
        weights[i] += weights[i - 1] || 0;

    var random = Math.random() * weights[weights.length - 1];

    for (i = 0; i < weights.length; i++)
        if (weights[i] > random)
            break;

    return items[i];
}

截至 2020 年 12 月,我用这个解决方案替换了我的旧 ES6 解决方案,因为旧浏览器不支持 ES6,我个人认为这个更具可读性。

如果您更愿意使用具有属性 itemweight 的对象:

 function weighted_random(options) {
    var i;

    var weights = [];

    for (i = 0; i < options.length; i++)
        weights[i] = options[i].weight + (weights[i - 1] || 0);

    var random = Math.random() * weights[weights.length - 1];

    for (i = 0; i < weights.length; i++)
        if (weights[i] > random)
            break;

    return options[i].item;
}

解释:

我制作了这张图表来展示它是如何工作的:

图表显示了项目的权重以及它们如何加起来以及如何与随机数交互。如果没有这张图,这个解释就不是很有帮助,所以如果它不能为你呈现,请随时在评论中问我任何关于它的问题。

此图显示了当输入具有权重 [5, 2, 8, 3] 时会发生什么。通过对权重进行部分求和,您只需要找到第一个与随机数一样大的权重,即随机选择的项目。

如果在两个权重的边界上选择一个随机数,例如图中的 715 ,我们选择较长的一个。这是因为 0 可以被 Math.random 选择,但是 1 不能,所以我们得到了公平的分配。 If we went with the shorter one, A could be chosen 6 out of 18 times ( 0 , 1 , 2 , 3 , 4 ),赋予它比应有的更高的权重。

原文由 Radvylf Programs 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题