proportionate
v1.0.1
Published
Convenience methods for dealing with proportions (a part, share, or number considered in comparative relation to a whole).
Downloads
35
Readme
The Proportionate Javascript Library
- The Proportionate Javascript Library
- Variation: Clamped Proportionate
- Why do I need it?
- Installation
- Example Usage
- Clamped variation
What it does
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.
How it does it
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.
Expected output
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 |
Variation: Clamped Proportionate
What it does
Clamped proportionate has the exact same interface, but only returns the extreme values when the input is equal to the extreme of the range.
How it does it
It uses the formula:
index = actual <= 0 ? 0 : actual >= max ? sampleSize - 1 : max(sampleSize, min(1, sampleSize * round((valueInRange - rangeMin) / (rangeMax - rangeMin)) - 2))
Expected output
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 |
Why do I need it?
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)
Installation
npm install --save proportionate
Example Usage
As a module:
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"
As a prototype on Array:
// 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"
Clamped variation
As a module:
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"
As a prototype on Array:
// 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