Skip to content

Instantly share code, notes, and snippets.

@asqd
Created April 18, 2024 23:27
Show Gist options
  • Save asqd/9b2a67af05a2b718b3cb81cca5d07eff to your computer and use it in GitHub Desktop.
Save asqd/9b2a67af05a2b718b3cb81cca5d07eff to your computer and use it in GitHub Desktop.
Lightweight module to pick a random element from a weighted array
class Picker {
/**
* @param {Function} [randomFn] Random number generator
*/
constructor(randomFn = Math.random) {
this.random = randomFn;
}
/**
* Pick a random value based on its weight.
* @param {Array} data Array of values.
* @return {Mixed}
*/
pick(data) {
if (!Array.isArray(data) || data.length === 0) {
throw new TypeError('Expected a non-empty Array as the first argument');
}
const totalWeight = data.reduce((sum, item) => sum + item[1], 0);
const rand = this.random() * totalWeight;
let weightSum = 0;
for (const [value, weight] of data) {
weightSum += weight;
if (rand <= weightSum) {
return value;
}
}
// Fallback in case of unexpected error
return data[data.length - 1][0];
}
}
const pick = (data, randomFn) => {
const picker = new Picker(randomFn);
return picker.pick(data);
};
export default pick;
export { pick, Picker };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment