Skip to content

Instantly share code, notes, and snippets.

@orrgal1
Created February 12, 2019 19:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save orrgal1/6d3514f7c275990fa1ebe9bfb9b0a64f to your computer and use it in GitHub Desktop.
Save orrgal1/6d3514f7c275990fa1ebe9bfb9b0a64f to your computer and use it in GitHub Desktop.
Efficient random element from weighted array
//get a random weighted element in O(n) time and O(n) space
const randomWeightedElement = (elems, weightFn) => {
if(!elems || !elems.length) return;
const weighted = [];
let sum = 0;
for (let elem of elems) {
const weight = weightFn(elem);
if (weight > 0) {
sum += weight;
weighted.push({ elem, boundary: sum });
}
}
const rand = random() * sum;
for (let elem of weighted) {
if (elem.boundary >= rand) {
return elem.elem;
}
}
//last element
return elems[elems.length-1];
};
//depending on the nature of weightFn, could also do this in constant space without building the array by just looping twice
const randomWeightedElement2 = (elems, weightFn) => {
if(!elems || !elems.length) return;
let sum = 0;
for (let elem of elems) {
const weight = weightFn(elem);
if (weight > 0) {
sum += weight;
}
}
const rand = random() * sum;
sum = 0;
for (let elem of elems) {
const weight = weightFn(elem);
if (weight > 0) {
sum += weight;
}
if (sum >= rand) {
return elem.elem;
}
}
//last element
return elems[elems.length-1];
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment