php 45 lines · 8 steps

Weighted random selection in PHP

Pick a variant at random with each option's odds proportional to its assigned weight.

Explained by highlit
1<?php
2 
3namespace App\Experiments;
4 
5use InvalidArgumentException;
6 
7final class WeightedVariantPicker
8{
9 private array $variants;
10 private int $total;
11 
12 public function __construct(array $weights)
13 {
14 if ($weights === []) {
15 throw new InvalidArgumentException('At least one variant is required.');
16 }
17 
18 $this->variants = [];
19 $cumulative = 0;
20 
21 foreach ($weights as $name => $weight) {
22 if ($weight <= 0) {
23 throw new InvalidArgumentException("Weight for \"{$name}\" must be positive.");
24 }
25 
26 $cumulative += $weight;
27 $this->variants[] = ['name' => $name, 'threshold' => $cumulative];
28 }
29 
30 $this->total = $cumulative;
31 }
32 
33 public function pick(): string
34 {
35 $roll = random_int(1, $this->total);
36 
37 foreach ($this->variants as $variant) {
38 if ($roll <= $variant['threshold']) {
39 return $variant['name'];
40 }
41 }
42 
43 return $this->variants[array_key_last($this->variants)]['name'];
44 }
45}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Turning weights into cumulative thresholds lets a single random roll map cleanly to a weighted choice.
  2. 2Validating inputs in the constructor keeps the sampling method simple and always correct.
  3. 3A final fallback return guards against floating-point or off-by-one gaps in threshold coverage.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Weighted random selection in PHP — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code