@naturalcycles/js-lib
Version:
Standard library for universal (browser + Node.js) javascript
86 lines (85 loc) • 2.58 kB
JavaScript
import { _average, _percentile, _percentiles } from './math.util.js';
/**
* Implements a "round-robin" Stack ("first-in last-out" aka FILO) with a limited size.
* Like an array of a fixed size. When it runs out of space - it starts writing on top of itself
* from index 0.
*
*
*/
export class Stack {
size;
constructor(size) {
this.size = size;
}
/**
* Index of a slot to get written TO next.
* Currently this slot contains OLDEST item (if any).
*/
nextIndex = 0;
items = [];
push(item) {
this.items[this.nextIndex] = item;
this.nextIndex = this.nextIndex === this.size - 1 ? 0 : this.nextIndex + 1;
return this;
}
/**
* Fill (overwrite) the whole Stack (all its items) with the passed `item`.
*/
fill(item) {
for (let i = 0; i < this.size; i++) {
this.items[i] = item;
}
return this;
}
/**
* Returns last items in the right order.
* Unlike raw `items` property that returns "items buffer" as-is (not ordered properly).
*/
get itemsOrdered() {
if (this.items.length < this.size) {
// Buffer is not filled yet, just return it as-is
return this.items;
}
// Buffer was filled and started to "overwrite itself", will need to return 2 slices
return [...this.items.slice(this.nextIndex), ...this.items.slice(0, this.nextIndex)];
}
}
/**
* Fixed-size FILO stack of Numbers.
* Has convenience stat methods, e.g percentile, avg, etc.
*/
export class NumberStack extends Stack {
avg() {
// _assert(this.items.length, 'NumberStack.avg cannot be called on empty stack')
return _average(this.items);
}
/**
* Returns null if Stack is empty.
*/
avgOrNull() {
return this.items.length === 0 ? null : _average(this.items);
}
median() {
return _percentile(this.items, 50);
}
medianOrNull() {
return this.items.length === 0 ? null : _percentile(this.items, 50);
}
/**
* `pc` is a number from 0 to 100 inclusive.
*/
percentile(pc) {
// _assert(this.items.length, 'NumberStack.percentile cannot be called on empty stack')
return _percentile(this.items, pc);
}
/**
* `pc` is a number from 0 to 100 inclusive.
* Returns null if Stack is empty.
*/
percentileOrNull(pc) {
return this.items.length === 0 ? null : _percentile(this.items, pc);
}
percentiles(pcs) {
return _percentiles(this.items, pcs);
}
}