frank-houweling / weighted-random
Library for generating a weighted random sample
Installs: 1 427
Dependents: 0
Suggesters: 0
Security: 0
Stars: 2
Watchers: 1
Forks: 5
Open Issues: 0
Requires
- php: ^7.3
- beberlei/assert: ^3.2
Requires (Dev)
- phpunit/phpunit: ^8
- squizlabs/php_codesniffer: ^3.3
- vimeo/psalm: ^3.4
This package is auto-updated.
Last update: 2025-03-28 08:20:41 UTC
README
This library is used to pick random values from a set of registered values, where values with a higher weight have a larger probability to be picked.
Installing
Install this library using composer.
composer require frank-houweling/weighted-random
Getting started
Using this library is simple. Initiate the WeightedRandomGenerator, register the possible values, and start generating random values!
<?php use FrankHouweling\WeightedRandom\WeightedRandomGenerator; // Initiate the generator $generator = new WeightedRandomGenerator(); // Register some value $generator->registerValue('foobar', 5); // And get a random value echo $generator->generate() . PHP_EOL;
Registering values
You can set one value with its weight using the following method. A higher weight means a higher probability that the value is generated by the random generator.
<?php use FrankHouweling\WeightedRandom\WeightedRandomGenerator; // Initiate the generator $generator = new WeightedRandomGenerator(); // Register a new value $generator->registerValue('foobar', 5); // Override the added value with a weight of 1 $generator->registerValue('foobar', 1); // The weight should be above 0, this call will result in an \InvalidArgumentException $generator->registerValue('foobar', 0);
You can register multiple values at once with the registerValues() method. This method only accepts strings an integers as values.
The registerValues() methods expects the value to be the key, and the weight to be the value of the passed array.
<?php use FrankHouweling\WeightedRandom\WeightedRandomGenerator; $generator = new WeightedRandomGenerator(); // Register multiple values $generator->registerValues([ 'foo' => 1, 'bar' => 2, ]); // Override the bar, foo will stay the same. $generator->registerValues([ 'bar' => 1, ]); // This will result in an InvalidArgumentException, 0 is not a correct weight. $generator->registerValues([ 'bar' => 0, ]);
You can remove a value from the generator with the removeValue method.
<?php use FrankHouweling\WeightedRandom\WeightedRandomGenerator; $generator = new WeightedRandomGenerator(); $generator->registerValue('foobar', 2); $generator->removeValue('foobar');
If you prefer, you can also use the WeightedValue valueobject. You should use the registerWeightedValue and removeWeightedValue methods to register and remove values with these value objects.
<?php use FrankHouweling\WeightedRandom\WeightedRandomGenerator; use FrankHouweling\WeightedRandom\WeightedValue; $generator = new WeightedRandomGenerator(); $weightedValue = new WeightedValue('foobar', 2); $generator->registerWeightedValue($weightedValue); $generator->removeWeightedValue($weightedValue);
Retrieving registered values
You can retrieve registered values and their weights from the generator. These are always returns as WeightedValue valueobjects.
<?php use FrankHouweling\WeightedRandom\WeightedRandomGenerator; $generator = new WeightedRandomGenerator(); $generator->registerValues([ 'foo' => 2, 'bar' => 3, ]); // Retrieve all registered values foreach ($generator->getWeightedValues() as $weightedValue) { echo sprintf( '%s => %s', $weightedValue->getValue(), $weightedValue->getWeight() ) . PHP_EOL; } // Or only one, by the given value. $weightedValue = $generator->getWeightedValue('foo'); echo $weightedValue->getWeight() . PHP_EOL;
Generating a random sample
To generate a random sample from the registered values, we use the generate method.
Generated values are not always unique. It is possible that calling the generate method twice will return in the same value twice.
<?php use FrankHouweling\WeightedRandom\WeightedRandomGenerator; $generator = new WeightedRandomGenerator(); $generator->registerValue('foo', 2); // Because we only registered one value, this now always returns `foobar` echo $generator->generate() . PHP_EOL; $generator->registerValue('bar', 2); // Because we have registered two values, both with a weight of 2, the chance of foo and bar is both 50%. echo $generator->generate() . PHP_EOL;
You can also generate a sample of multiple values using the generateMultiple method, and a set of multiple values without a possibility of duplicates with generateMultipleWithoutDuplicates.
<?php use FrankHouweling\WeightedRandom\WeightedRandomGenerator; $generator = new WeightedRandomGenerator(); $generator->registerValues([ 'foo' => 2, 'bar' => 2, ]); // Can return foo + bar, bar + foo, foo + foo or bar + bar. foreach ($generator->generateMultiple(2) as $value) { echo $value . PHP_EOL; } // Can return foo + bar or bar + foo foreach ($generator->generateMultipleWithoutDuplicates(2) as $value) { echo $value . PHP_EOL; } // This will return three values, of which 2 or 3 are duplicate. $generator->generateMultiple(3); // This will throw an \InvalidArgumentException, because it is not possible to generate three unique values. $generator->generateMultipleWithoutDuplicates(3);