将变量设置为数组中的随机项时如何指定机会?

Dis*_*ame 6 command-line array random variable

目前我这样做是为了将变量设置为数组中的随机项:

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

var=${array[$RANDOM % ${#array[@]} ]}
Run Code Online (Sandbox Code Playgroud)

如果我想设置$var为这些值之一,但指定变量将分别设置为每个项目的值的机会,我该怎么办?假设我想要 73.3% 的机会foo,26.6% 的机会bar,以及 0.1% 的机会baz

Jef*_*ler 6

一种方法:建立一个具有相应百分比机会的平行阵列;下面,我将它们缩放到 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"
Run Code Online (Sandbox Code Playgroud)


Dop*_*oti 6

shell 不能做浮点运算,但是如果我们只是移动小数点,我们可以使用$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
Run Code Online (Sandbox Code Playgroud)

这样做的优点是不必将数组炸毁多达 1000 个条目或不需要任何for循环。