【问题标题】:Assign probabilities to shuffle in Javascript在 Javascript 中分配随机播放的概率
【发布时间】:2021-10-04 22:36:03
【问题描述】:

我有以下数组:

var myArray =  [BF1,BA1,BF2, BA2, BF3,BA3, BA4, BF4 , BA5, BF5, BF6, BA6, BF7, BA7, BA8, BF8, BA9, BF9, 
                BF10, BA10, BA11, BF11, BA12, BF12, BA13, BF13, BA14, BF14, BA15, BF15, BA16, BF16, BF17, BA18, 
                BF18, BA19, BF19, BA20, BF20, BA21, BF21, BF22, BA22, BA23, BF23, BA24, BF24, BA25, BF25, BA26, 
                BA27, BF27, BA28, BF28, WA29, WA30, WF30, WA31, WA31, WF32, WA32, WF33, WA33, WF34, WA34, 
                WF35, WA35, WA36, WA37, WA38, WF38, WA39, WF40, WA40, WA41, WF41, WA42, WF42, WF43, WA43, 
                WF44, WA44, WF45, WA45, WF46, WF46, WA47, WF47, WA48, WF48, WF49, WA49, WA50, WF50, WF51, 
                WA51];

我使用下面的函数来洗牌,这样shuffle(myArray);

function shuffle(array){
    var counter = array.length,
        temp, index;
    while (counter > 0){
        index = Math.floor(Math.random() * counter);
        counter = counter-1;
        temp = array[counter];
        array[counter] = array[index];
        array[index] = temp;
    }
    return array;

但是,我想用概率来洗牌。这样 myArray 中以 B 开头的项目 (BF1,BA1,BF2...BF28) 有 0.8 的概率成为数组中的第一个项目,并且以 W 开头的项目 (WA29,WA30,WF30...WA51)有 0.2 的概率成为数组中的第一项。

我可以使用 math.random 做到这一点吗?还是我应该使用其他东西?

提前致谢!

【问题讨论】:

  • 你到底是什么意思?通过“数组中的第一项”,您的意思是仅第一项具有该概率吗?或者每次比较有 0.8 的机会将 B 移动到 W 之前,有 0.2 的机会将 W 移动到 B 之前,如果它们具有相同的第一个字母,则交换项目的机会为 0.5?
  • 谢谢,也许这是措辞不当。我基本上使用这个函数从数组中选择一个项目(第一项)。所以另一种思考方式是,我基本上想从这个列表中随机选择一个项目,项目的概率 0.8 以 B 开头,0.2 以 W 开头。
  • 如果你有 100 个 B 项和 1 个 W 项怎么办?单个 W 项目是否有 20% 的机会成为第一?还是有 1/401 的机会成为第一?
  • 它将有 20% 的概率首先出现。我不打算让函数返回一个数组。就我而言,该函数每次都可以返回一个项目,该项目将有 20% 的概率先有 W,有 80% 的概率先有 B

标签: javascript arrays shuffle


【解决方案1】:

我将假设您的意思是,当您选择第一个项目时,“B”被加权,因此它们被首先选择的可能性是其 4 倍。例如,如果我们有两个项目 B1 和 W1,则有 80% 的机会以 ['B1', 'W1'] 结束,20% 的机会以 ['W1', 'B1'] 结束。如果您有四个项目 B1、W1、W2、W3,那么将有 80/140 的机会首先获得 B1(加权),并且有 20/140 的机会获得 W1、W2 或 W3 中的每一个。如果 B1 是第一个,则剩余的 W 项都有相同的机会成为下一个。如果 W 是第一,那么 B1 有 80/120 的机会成为第二。等等……

这样做的一种方法是权衡剩余列表中的每个项目,并根据总概率计算一个随机数,然后逐步遍历列表,直到达到该数字。例如,您将有 B1 = 0.8、B2 = 0.8、W1 = 0.2、W2 = 0.2。所以你计算一个随机数 >0 = 并且

对于一个包含两个字符的简单列表,将数组拆分为 W 和 B 会更快,然后为每个组成一个数组,然后计算一个随机数(加权)从哪个数组中选择,然后再计算另一个随机数从该数组中选择哪个项目。

var myArray =  ['BF1','BA1','BF2','BA2','BF3','BA3','BA4',
'BF4','BA5','BF5','BF6','BA6','BF7','BA7',
'BA8','BF8','BA9','BF9','BF10','BA10',
'BA11','BF11','BA12','BF12','BA13','BF13',
'BA14','BF14','BA15','BF15','BA16','BF16',
'BF17','BA18','BF18','BA19','BF19','BA20',
'BF20','BA21','BF21','BF22','BA22','BA23',
'BF23','BA24','BF24','BA25','BF25','BA26',
'BA27','BF27','BA28','BF28','WA29','WA30',
'WF30','WA31','WA31','WF32','WA32','WF33',
'WA33','WF34','WA34','WF35','WA35','WA36',
'WA37','WA38','WF38','WA39','WF40','WA40',
'WA41','WF41','WA42','WF42','WF43','WA43',
'WF44','WA44','WF45','WA45','WF46','WF46',
'WA47','WF47','WA48','WF48','WF49','WA49',
'WA50','WF50','WF51','WA51'];
                
const shuffle = arr => {
  let bs = [], ws = [];
  arr.forEach(ele => {
    if (ele[0] === 'B') {
      bs.push(ele);
    } else {
      ws.push(ele);
    }
  });
  
  let result = [];
  while (bs.length > 0 || ws.length > 0) {
    let bProbability = bs.length * 0.8;
    let wProbability = ws.length * 0.2;
    let totalProbability = bProbability + wProbability;
    let whichRandom = Math.random() * totalProbability;
    if (whichRandom < bProbability) {
      let index = whichRandom * 
          bs.length / bProbability;
      result.push(bs.splice(index, 1));
    } else {
      let index = (whichRandom - bProbability) *
          ws.length / wProbability;
      result.push(ws.splice(index, 1));
    }
  }
  return result;
}

let sorted = shuffle(myArray);
console.log(sorted);

【讨论】:

    【解决方案2】:

    您可以使用此函数生成(伪)随机数,如果它小于概率(介于 0 和 1 之间,区间:[0,1)),则返回真或假。取决于结果,你可以或不做一些动作:

    const isInProbability = (probability) => {
      const rand = Math.random();
      return rand < probability;
     };
    

    记住 Math.random() 是一个伪随机数。如果您需要更高的安全性,请使用 crypto.getRandomValues() (https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Math/random)

    【讨论】:

      猜你喜欢
      • 2021-04-27
      • 2023-01-23
      • 2019-06-30
      • 2011-04-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-26
      • 2011-10-20
      相关资源
      最近更新 更多