I had the same question, yet the checked was not working for my needs: I was searching for a function that rolls a dice on (any) elements in an array, based on their given probabilities. Thats what I came up with:
/**
* Dices a value from a given list with percentages.
*
* Input be like
* [
* 0 => 10.5,
* 1 => 9.2,
* '2.4' => 30,
* 'foo' => 50.3,
* ]
*
* If sum of $probabilities don't add up to 100, 100 is used to dice against and will maybe hit the fallback.
* If sum of $probabilities is more than 100, all given $probabilities will be spread accordingly.
*
* @param array $probabilities
* @param mixed $fallback
* @return mixed
*/
public static function diceOnArray(array $probabilities, mixed $fallback = null): mixed
{
$sum = max(100, array_sum($probabilities));
$fallback = $fallback ?: array_key_first($probabilities);
$random = rand(0, $sum);
foreach ($probabilities as $key => $probability) {
if ($random > $probability) {
$random -= $probability;
continue;
}
return $key;
}
// hit nothing from the list, use fallback
return $fallback;
}
I added the fallback functionality, because I often have collections not summing um to 100 (like 10%, 20% thats it) and therefore I just put $array[0] as the fallback into the function which in a way adds up the first value to what's left to 100%.
Cheers andi