I want to pseudo-randomly pick one element from an array of 5 elements: I want to control the occurrence probability of each of those 5 elements.
Example: I have an array like this: [A B C D E]
- I want the probability to pick A: 0.10 (10%)
- I want the probability to pick B: 0.10 (10%)
- I want the probability to pick C: 0.20 (20%)
- I want the probability to pick D: 0.20 (20%)
- I want the probability to pick E: 0.40 (40%)
I have seen that I can weight a random selection from an array here: Weighted random selection from array.
How can I weight elements contained in an array like this?
TylerH
21.3k84 gold badges84 silver badges121 bronze badges
1 Answer 1
You'd use the bash builtin variable RANDOM, with a little arithmetic
weighted_selection() {
local ary=("$@")
case $(( RANDOM % 10 )) in
0) index=0 ;; # one out of ten
1) index=1 ;; # one out of ten
2|3) index=2 ;; # two out of ten
4|5) index=3 ;; # two out of ten
*) index=4 ;; # remaining is four out of ten
esac
echo ${ary[index]}
}
Let's test it:
a=(A B C D E)
declare -A count
for ((i=1; i<1000; i++)); do
(( count[$(weighted_selection "${a[@]}")]++ ))
done
declare -p count
outputs
declare -A count='([A]="99" [B]="100" [C]="211" [D]="208" [E]="381" )'
answered Mar 5, 2019 at 23:36
glenn jackman
249k42 gold badges233 silver badges362 bronze badges
Sign up to request clarification or add additional context in comments.
2 Comments
chepner
RANDOM ranges from 0 to 32767, so this really produces a distribution like 10.006%/10.006%/20.012%/20.012%/39.99%. If that difference matters (and it probably shouldn't), you could do something like x=32768; until (( x < 32760 )); x=$RANDOM, then check $x % 10.Soma Hesk
does it have go version for this algo?
lang-bash