- The Proportionate Javascript Library
- Variation: Clamped Proportionate
- Why do I need it?
- Installation
- Example Usage
- Clamped variation
Convenience methods for dealing with proportions (a part, share, or number considered in comparative relation to a whole).
Specifically it allows you to select something from an array indexed proportionate to a number within an arbitrary range.
Useful when you need to select from a small list of things given a broad range of options.
It takes the form:
proportionate(sampleArray, valueInRange, [rangeMax(orMin), [rangeMax]]) => sample
It uses the formula:
index = max(sampleSize, min(0, sampleSize * round((part - rangeMin) / (rangeMax - rangeMin)) - 1))
SampleArray and valueInRange are required arguments. SampleArray must be an array. RangeMin and rangeMax default to 0 and 99, respectively. If you specify one range argument, it's 0..rangeMax, but if you specify both, it's rangeMin..rangeMax.
Given the sampleArray: [1, 2, 3]
And the (default) range: 0, 99
Or in functional notation:
[0..99].map(x -> proportionate([1, 2, 3], x))
The expected truth table would be:
Input | Output |
---|---|
0-32 | 1 |
33-65 | 2 |
66-99 | 3 |
Clamped proportionate has the exact same interface, but only returns the extreme values when the input is equal to the extreme of the range.
It uses the formula:
index = actual <= 0 ? 0 : actual >= max ? sampleSize - 1 : max(sampleSize, min(1, sampleSize * round((valueInRange - rangeMin) / (rangeMax - rangeMin)) - 2))
Given the sampleArray: [1, 2, 3]
And the (default) range: 0, 99
Or in functional notation:
[0..99].map(x -> proportionate([1, 2, 3], x))
The expected truth table would be:
Input | Output |
---|---|
0 | 1 |
1-98 | 2 |
99 | 3 |
It's shorthand for the following rather unreadable code, seen many times in the wild:
array[Math.max(array.length, Math.min(0, array.length * Math.round((actual - min) / (max - min)) - 1))]
It replaces it with:
proportionate(array, actual, min, max)
Or, assuming a min of 0:
proportionate(array, actual, max)
Or, assuming a range of 0..99:
proportionate(array, actual)
Or, when using the Array.prototype option:
array.proportionate(actual, min, max)
array.proportionate(actual, max)
array.proportionate(actual)
npm install --save proportionate
var proportionate = require("proportionate");
var weightRanks = ["fly", "light", "medium", "heavy", "super-heavy"];
//Default range of 0..99
proportionate(weightRanks, 10); // "fly"
proportionate(weightRanks, 25); // "light"
proportionate(weightRanks, 45); // "medium"
proportionate(weightRanks, 65); // "heavy"
proportionate(weightRanks, 85); // "super-heavy"
//Range of 0..500
proportionate(weightRanks, 50, 500); // "fly"
proportionate(weightRanks, 150, 500); // "light"
proportionate(weightRanks, 250, 500); // "medium"
proportionate(weightRanks, 350, 500); // "heavy"
proportionate(weightRanks, 450, 500); // "super-heavy"
//Range of 80..350
proportionate(weightRanks, 90, 80, 350); // "fly"
proportionate(weightRanks, 180, 80, 350); // "light"
proportionate(weightRanks, 240, 80, 350); // "medium"
proportionate(weightRanks, 290, 80, 350); // "heavy"
proportionate(weightRanks, 330, 80, 350); // "super-heavy"
// This installs .proportionate on Array.prototype:
require("proportionate/arrays");
//This also works:
require("proportionate").arrays();
var weightRanks = ["fly", "light", "medium", "heavy", "super-heavy"];
//Default range of 0..99
weightRanks.proportionate(10); // "fly"
weightRanks.proportionate(25); // "light"
weightRanks.proportionate(45); // "medium"
weightRanks.proportionate(65); // "heavy"
weightRanks.proportionate(85); // "super-heavy"
//Range of 0..500
weightRanks.proportionate(50, 500); // "fly"
weightRanks.proportionate(150, 500); // "light"
weightRanks.proportionate(250, 500); // "medium"
weightRanks.proportionate(350, 500); // "heavy"
weightRanks.proportionate(450, 500); // "super-heavy"
//Range of 80..350
weightRanks.proportionate(90, 80, 350); // "fly"
weightRanks.proportionate(180, 80, 350); // "light"
weightRanks.proportionate(240, 80, 350); // "medium"
weightRanks.proportionate(290, 80, 350); // "heavy"
weightRanks.proportionate(330, 80, 350); // "super-heavy"
var proportionate = require("proportionate/clamped");
var tankFullness = ["empty", "almost empty", "half-full", "mostly full", "completely full"];
//Default range of 0..99
tankFullness.proportionate(0); // "empty"
tankFullness.proportionate(1); // "almost empty"
tankFullness.proportionate(45); // "half-full"
tankFullness.proportionate(98); // "mostly full"
tankFullness.proportionate(99); // "completely full"
// This installs .proportionate on Array.prototype:
require("proportionate/clamped/arrays");
//This also works:
require("proportionate/clamped").arrays();
var tankFullness = ["empty", "almost empty", "half-full", "mostly full", "completely full"];
//Default range of 0..99
tankFullness.proportionate(0); // "empty"
tankFullness.proportionate(1); // "almost empty"
tankFullness.proportionate(45); // "half-full"
tankFullness.proportionate(98); // "mostly full"
tankFullness.proportionate(99); // "completely full"
Pull requests are welcome, please file any bugs on https://github.com/tsavo/proportionate-js