对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' ] ]

如果您生成了足够的数据,它将不符合所需的订单/分配。


解决方案

我认为问题陈述不当。

按照规定,A在第1位的概率为60%,B在第2位的概率为20%,C和D在第3位或第4位,各占10%。没有满足这些概率标准的分布,因此没有任何算法可以产生它:如果在60%的情况下A位于第1位,则C或D必须在这60%的第3位或第4位,因此这远远高于所需的10%概率。

因此,这里的第一个任务是理解问题中所写的内容(因为在解释之后,它当然是有意义的)。

我想A的60%和B的20%不应该被解读为概率,而是一种人气。但这不能只是每个候选人的法定人数,因为在投票过程中,A将在100%的情况下排在第一位。

那么,让我们假设一个包含一些随机性的投票过程,其中A以60%的概率排在第1位,B排在第1位(!)概率为20%,然后我们可以对位置1使用加权随机选择来实现这一点。

如何继续位置2..n?我们只是保持权重不变,并删除已经被选中的候选人。如果其他候选人中有一人排到了第一名,那么这将很有可能出现在第二名,我认为这是有意义的。

相关文章