Weighted Random Selection
PHP Code Editor
Execution Result
Ready to execute
Click the "Run Script" button to see the output here
Description
When you need to pick an option but not uniformly, weighted random selection gives each candidate a chance proportional to its weight. It shows up in load balancing across unequal servers, A/B bucketing with uneven splits, and picking a random item where some are rarer than others. The naive approach of building an array with one entry per weight unit wastes memory when weights are large.
This version avoids that by using cumulative weights. It sums the total once, draws a single integer in that range, then walks the entries accumulating their weights and returns the first key whose running total reaches the draw. That is one pass over the candidates and no expansion of the weights into a big array, so it stays cheap even when weights are in the thousands.
function weightedRandom(array $weights): string|int {
$total = array_sum($weights);
if ($total <= 0) {
throw new InvalidArgumentException('weights must sum to a positive number');
}
$draw = random_int(1, (int) $total);
$cumulative = 0;
foreach ($weights as $key => $weight) {
$cumulative += $weight;
if ($draw <= $cumulative) {
return $key;
}
}
return array_key_last($weights);
}
$weights = ['common' => 70, 'uncommon' => 25, 'rare' => 5];
$counts = ['common' => 0, 'uncommon' => 0, 'rare' => 0];
for ($i = 0; $i < 10000; $i++) {
$counts[weightedRandom($weights)]++;
}
print_r($counts); // roughly 7000 / 2500 / 500
Comments
No comments yet
Be the first to share your thoughts!