Created
December 2, 2021 21:15
-
-
Save DinoChiesa/b29bd3c3ab2a6a0ed764509196684372 to your computer and use it in GitHub Desktop.
perform a weighted random selection in JS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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