UNPKG

sangja

Version:

JavaScript data structures library

175 lines (154 loc) 4.13 kB
const Utils = require('./utils'); /** * @class * @memberof sangja */ class Stack { /** * Creates a new Stack. * Iterable parameter is optional. * @constructor * @param {iterable} [iterable] - Iterator for initialize the stack. * @throws {TypeError} When given parameter is not stack. */ constructor(iterable = []) { if (!Utils.isIterable(iterable)) { throw TypeError(); } this._stack = [...iterable]; } /** * Add value at the top of the stack. * @param {*} value - The value to push to the stack. */ push(value) { this._stack.push(value); } /** * Add values in the given iterator at the top of the stack. * @param {iterable} iterable - The iterable values to push to the stack. */ pushAll(iterable) { [...iterable].forEach(v => this._stack.push(v)); } /** * Removes the top of the stack and returns the value at the top of the stack. * @returns {*} The value at the top of the stack. If empty, return undefined. */ pop() { if (this._stack.length === 0) { return undefined; } return this._stack.pop(); } /** * Returns the value at the top of the stack without changing the state of the stack. * @returns {*} The value at the top of the stack. If empty, return undefined. */ top() { if (this._stack.length === 0) { return undefined; } return this._stack[this._stack.length - 1]; } /** * Removes all values in the stack. */ clear() { this._stack = []; } /** * Returns the number of elements in the stack. * @returns {number} The number of elements in the stack. */ size() { return this._stack.length; } /** * Returns whether the stack is empty. * @returns {boolean} True if the stack is empty. */ isEmpty() { return this._stack.length === 0; } /** * For each values in the stack, execute the given procedure f.<br> * *Executing order is top to bottom* * @param {function} f - Procedure to execute */ forEach(f) { for (let i = this._stack.length - 1; i >= 0; i -= 1) { f(this._stack[i]); } } /** * Returns a stack whose values are mapped with given function f. * @param {function} f - Function to map values * @return {Stack} Stack([mapped values]) */ map(f) { const stack = new Stack(); stack._stack = this._stack.map(f); return stack; } /** * Returns a stack whose values are mapped with given function f and flattened. * @param {function} f - Function (this.value) => iterable * @return {Stack} Stack([mapped and flattened values]) */ flatMap(f) { const stack = new Stack(); // [...this._stack.map(f)].forEach(arr => arr.forEach(v => stack.push(v))); this._stack.map(f).forEach(arr => stack.pushAll(arr)); return stack; } /** * Returns a stack whose values are filtered with given predicate f. * @param {function} f - Predicate (this.value) => boolean * @return {Stack} Stack([filtered values]) */ filter(f) { const stack = new Stack(); stack._stack = this._stack.filter(f); return stack; } /** * Returns a stack whose values are reversed in order. * @return {Stack} Stack([reversed values]) */ reversed() { return new Stack(this); } /** * If any of containing values satisfies given f, return true. * If none of values satisfy f or not contain any value, return false. * @param {function} f - Predicate * @returns {boolean} */ some(f) { return this._stack.some(f); } /** * If all of containing values satisfies given f or not contain any value, return true. * If any of value doesn't satisfy f, return false. * @param {function} f - Predicate * @returns {boolean} */ every(f) { return this._stack.every(f); } /** * If contains given value v, return true. * @param {*} v * @returns {boolean} */ includes(v) { return this._stack.includes(v); } * [Symbol.iterator]() { for (let i = this._stack.length - 1; i >= 0; i -= 1) { yield this._stack[i]; } } } module.exports = Stack;