Skip to content

Instantly share code, notes, and snippets.

@DinoChiesa
Created December 2, 2021 21:15
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 DinoChiesa/b29bd3c3ab2a6a0ed764509196684372 to your computer and use it in GitHub Desktop.
Save DinoChiesa/b29bd3c3ab2a6a0ed764509196684372 to your computer and use it in GitHub Desktop.
perform a weighted random selection in JS
// weightedRandomSelector.js
//
// This is a simple weighted random selector, works in Rhino, can use within an
// Apigee JavaScript step.
//
// last saved: <2021-December-02 13:11:16>
//
// --------------------------------------------------------
(function (){
function WeightedRandomSelector(a) {
// This implements a weighted random selector, over an array. The argument a
// must be an array of elements, each of which has a weight property. The
// items need not be sorted in any particular order, and the weights need
// not sum to any particular value. Example usage:
//
// var routingTable = [
// { "name" : "A", "url": "https://a.example.com", "weight": 6 },
// { "name" : "B", "url": "https://b.example.com", "weight": 16 },
// { "name" : "C", "url": "https://c.example.com", "weight": 50 },
// { "name" : "D", "url": "https://d.example.com", "weight": 2 }
// ];
//
// var wrs = new WeightedRandomSelector(routingTable);
// var selected = wrs.select();
// var selectedUrl = selected.url;
//
var i, L;
this.totalWeight = 0;
this.a = a;
this.selectionCounts = [];
this.weightThreshold = [];
// initialize
for (i = 0, L = a.length; i<L; i++) {
this.totalWeight += a[i].weight;
this.weightThreshold[i] = this.totalWeight;
this.selectionCounts[i] = 0;
}
}
WeightedRandomSelector.prototype.select = function() {
// 1. select a random value
var R = Math.floor(Math.random() * this.totalWeight),
i, L;
// 2. find the bucket that R value falls into.
for (i = 0, L = this.a.length; i < L; i++) {
if (R < this.weightThreshold[i]) {
this.selectionCounts[i]++;
return(this.a[i]);
}
}
// 3. return the selected item
return this.a[L - 1];
};
// export into the global namespace
if (typeof exports === "object" && exports) {
// works for nodejs
exports.WeightedRandomSelector = WeightedRandomSelector;
}
else {
// works in rhino
var globalScope = (function(){ return this; }).call(null);
globalScope.WeightedRandomSelector = WeightedRandomSelector;
}
}());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment