当前位置:首页 > 行业动态 > 正文

按给定几率进行随机抽取的js代码

javascript,const randomPick = (probs) => {, const keys = Object.keys(probs);, let rand = Math.random();, let sum = 0;, for (let key of keys) {, sum += probs[key];, if (rand < sum) return key;, }, return keys[keys.length-1];,};,``

问题分析

需要实现一个函数,根据给定的元素及其对应概率,按权重随机抽取其中一个元素,输入 [{name: 'A', probability: 0.5}, {name: 'B', probability: 0.3}, {name: 'C', probability: 0.2}],函数应按照概率随机返回 'A''B''C'


解决方案思路

  1. 计算总权重:将所有元素的 probability 相加,得到总权重。
  2. 生成随机数:在 [0, 总权重] 范围内生成一个随机数。
  3. 权重累加匹配:遍历元素,累加每个元素的权重,当累加值超过随机数时,返回当前元素。
  4. 处理边界情况:过滤掉概率为 0 的元素,避免无效匹配。

代码实现

/
  根据给定概率随机抽取元素
  @param {Array} items 元素数组,每个元素需包含 { name, probability }
  @returns {Object|null} 被抽中的元素,或 null(若总权重为 0)
 /
function randomSelect(items) {
  // 过滤掉概率为 0 的元素
  const validItems = items.filter(item => item.probability > 0);
  const totalWeight = validItems.reduce((sum, item) => sum + item.probability, 0);
  // 如果总权重为 0,返回 null
  if (totalWeight === 0) return null;
  // 生成 [0, totalWeight) 范围内的随机数
  const randomNum = Math.random()  totalWeight;
  let currentWeight = 0;
  // 遍历元素,累加权重直到超过随机数
  for (const item of validItems) {
    currentWeight += item.probability;
    if (randomNum < currentWeight) {
      return item; // 返回当前元素
    }
  }
  // 处理浮点数精度问题(理论上不会执行到这里)
  return validItems[validItems.length 1];
}

示例说明

输入

const items = [
  { name: 'A', probability: 0.5 },
  { name: 'B', probability: 0.3 },
  { name: 'C', probability: 0.2 }
];

调用

const result = randomSelect(items);
console.log(result.name); // 可能输出 'A'、'B' 或 'C'

运行逻辑

  1. 总权重为 5 + 0.3 + 0.2 = 1
  2. 生成随机数 rand6)。
  3. 累加权重:
    • A 的权重 5.6 > 0.5,继续。
    • B 的权重 3,累加后 86 < 0.8,返回 B

相关问题与解答

问题1:如果输入数组中元素的概率总和不等于1,代码是否能正确工作?

解答
是的,代码会自动计算所有有效元素的总权重(totalWeight),并基于该值生成随机数,若输入概率总和为 2,则随机数范围为 [0, 2),权重占比逻辑仍然成立,无需手动归一化概率。


问题2:如何处理概率为0的元素?

解答
代码会通过 filter 方法过滤掉 probability === 0 的元素,确保它们不参与随机抽取,输入 [{name: 'D', probability: 0}] 时,函数会直接返回 null(因总权重

0