変数を配列の任意の項目に設定するときの確率をどのように指定しますか?

変数を配列の任意の項目に設定するときの確率をどのように指定しますか?

現在、私は配列内の任意の項目に変数を設定するために、次のことを行います。

array=("foo" "bar" "baz")

var=${array[$RANDOM % ${#array[@]} ]}

これらの値のいずれかに設定したいのですが、変数が各項目の値に個別に設定される可能性を指定した場合は$varどうなりますか? 73.3%の確率foo、26.6%の確率bar、0.1%の確率が欲しいとしましょうbaz

答え1

1つの方法は、並列配列を構築し、以下で対応するパーセンテージ確率を設定し、それを1000に調整することです。次に、1から1000までの任意の数字を選択し、機会がなくなるまで配列を繰り返します。

#!/bin/bash

array=( "foo"  "bar" "baz")
chances=(733    266     1)

choice=$((1 + (RANDOM % 1000)))
value=

for((index=0; index < ${#array[@]}; index++))
do
  choice=$((choice - ${chances[index]}))
  if [[ choice -le 0 ]]
  then
    value=${array[index]}
    break
  fi
done

[[ index -eq ${#array[@]} ]] && value=${array[index]}
printf '%s\n' "$value"

答え2

シェルは浮動小数点演算を実行できませんが、小数点だけ移動すると$RANDOM整数演算を使用できます。

#!/usr/local/bin/bash
array=("foo" "bar" "baz")
dieroll=$(($RANDOM % 1000))

if [[ "$dieroll" -lt 1 ]]; then
  printf "%s\n" "${array[2]}"
elif [[ "$dieroll" -lt 266 ]]; then
  printf "%s\n" "${array[1]}"
else
  printf "%s\n" "${array[0]}"
fi

これの利点は、配列を1000項目に増やしたりループを要求したりする必要がないことですfor

関連情報