UNPKG

@mezzy/collections

Version:

A luxurious user experience framework, developed by your friends at Mezzanine.

200 lines (167 loc) 6.39 kB
import CollectionTools from './collectionTools'; import IMapPair from './interfaces/iMapPair'; import IMap from './interfaces/iMap'; export class MapList<K, V> implements IMap<K, V> { /** * Creates an empty map. * @class <p>Dictionaries map keys to values; each key can map to at most one value. * This implementation accepts any kind of objects as keys.</p> * * <p>If the keys are custom objects a function which converts keys to unique * strings must be provided. Example:</p> * <pre> * function petToString(pet) { * return pet.key; * } * </pre> * @constructor * @param {function(Object):string=} _toStringFunction optional function used * to convert keys to strings. If the keys aren't strings or if _toStringing() * is not appropriate, a custom function which receives a key and returns a * unique string must be provided. */ constructor(_toStringFunction?:(key:K) => string) { this.table = {}; this.p_length = 0; this._toString = _toStringFunction || CollectionTools.defaultToString; } /** * Object holding the key-value pairs. * [key: K] will not work since indices can only be strings in javascript and typescript enforces this. */ private table:{ [key:string]:IMapPair<K, V> }; /** * Number of elements in the list. */ /** * Returns the number of keys in this map. * @return {number} the number of key-value mappings in this map. */ get size():number { return this.p_length; } protected p_length:number; /** * Function used to convert keys to strings. */ private _toString:(key:K) => string; /** * Returns the value to which this map maps the specified key. * Returns undefined if this map has no mapping for this key. * @param {Object} key key whose associated value is to be returned. * @return {*} the value to which this map maps the specified key or undefined if the map has no mapping for this key. */ get(key:K):V { let pair:IMapPair<K, V> = this.table[this._toString(key)]; if (CollectionTools.isUndefined(pair)) return undefined; return pair.value; } /** * Associates the specified value with the specified key in this map. * If the map previously contained a mapping for this key, the old * value is replaced by the specified value. * @param {Object} key key with which the specified value is to be associated. * @param {Object} value value to be associated with the specified key. * @return {*} previous value associated with the specified key, or undefined if there was no mapping for the key or if the key/value are undefined. */ set(key:K, value:V):V { if (CollectionTools.isUndefined(key) || CollectionTools.isUndefined(value)) return undefined; let ret:V; let k = this._toString(key); let previousElement:IMapPair<K, V> = this.table[k]; if (CollectionTools.isUndefined(previousElement)) { this.p_length++; ret = undefined; } else ret = previousElement.value; this.table[k] = { key: key, value: value }; return ret; } /** * Removes the mapping for this key from this map if it is present. * @param {Object} key key whose mapping is to be deleted from the map. * @return {*} value associated with specified key, or undefined if there was no mapping for key. */ delete(key:K):V { let k = this._toString(key); let previousElement:IMapPair<K, V> = this.table[k]; if (!CollectionTools.isUndefined(previousElement)) { delete this.table[k]; this.p_length--; return previousElement.value; } return undefined; } /** * Returns an array containing all of the keys in this map. * @return {Array} an array containing all of the keys in this map. */ get keys():K[] { let array:K[] = []; for (let name in this.table) { if ((<any>this.table).hasOwnProperty(name)) { let pair:IMapPair<K, V> = this.table[name]; array.push(pair.key); } } return array; } /** * Returns an array containing all of the values in this map. * @return {Array} an array containing all of the values in this map. */ get values():V[] { let array:V[] = []; for (let name in this.table) { if ((<any>this.table).hasOwnProperty(name)) { let pair:IMapPair<K, V> = this.table[name]; array.push(pair.value); } } return array; } /** * Executes the provided function once for each key-value pair * present in this map. * @param {function(Object, Object):*} callback function to execute, it is * invoked with two arguments: value and key. To break the iteration you can * optionally return false. */ forEach(callback:(value:V, key:K) => boolean):void { for (let name in this.table) { if ((<any>this.table).hasOwnProperty(name)) { let pair:IMapPair<K, V> = this.table[name]; let ret = callback(pair.value, pair.key); if (ret === false) return; } } } /** * Returns true if this map has a mapping for the specified key. * @param {Object} key key whose presence in this map is to be tested. * @return {boolean} true if this map has a mapping for the specified key. */ has(key:K):boolean { return !CollectionTools.isUndefined(this.get(key)); } /** * Removes all mappings from this map. * @this {CollectionTools.Map} */ clear() { this.table = {}; this.p_length = 0; } /** * Returns true if this map has no mappings. * @return {boolean} true if this map has no mappings. */ get isEmpty():boolean { return this.p_length <= 0; } toString():string { let toret = "{"; this.forEach((k, v):boolean => { toret = toret + "\n\t" + k.toString() + " : " + v.toString(); return true; }); return toret + "\n}"; } } // End class export default MapList;