UNPKG

trieste

Version:
338 lines (293 loc) 7.52 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global = global || self, global.trieste = factory()); }(this, function () { 'use strict'; /** * Adds string to trie (via object mutation). * * @param {string|Object} string * @param {Object} trie * @param {Object} options * @param {string} options.endKey * @param {*} options.endValue * @param {*} [endValue] */ function add(string, trie, options, endValue) { if (string instanceof Object) { for (var key in string) { add(key, trie, options, string[key]); } return; } if (!string || typeof string !== 'string') { return; } var endKey = options.endKey; endValue = arguments.length === 4 ? endValue : options.endValue; var node = trie; var letters = string.split(''); for ( var i = 0, lettersLength = letters.length, lettersLastIndex = lettersLength - 1; i < lettersLength; i++ ) { var letter = letters[i]; // use node with key if it exists; otherwise, create empty node node[letter] = node[letter] || {}; // update current node node = node[letter]; // last node of current string if (lettersLastIndex === i) { node[endKey] = endValue; } } } var add_1 = add; /** * The default end of string marker and value. * * The key `$$` ensures uniqueness since it has a length of 2. * The value `1` is a boolean integer of 1 byte. */ var constants = { END_KEY: '$$', END_VALUE: 1 }; /** * Checks if trie contains a string. * * @param {string} string * @param {Object} trie * @param {Object} options * @param {string} options.endKey * @return {boolean} */ function contains(string, trie, options) { if (!string || typeof string !== 'string') { return false; } var endKey = options.endKey; var letters = string.split(''); var node = trie; for (var i = 0, len = letters.length, lastIndex = len - 1; i < len; i++) { var key = letters[i]; if (!node.hasOwnProperty(key)) { return false; } node = node[key]; if (lastIndex === i) { return node.hasOwnProperty(endKey); } } } var contains_1 = contains; /** * Gets end of string value from trie. * * @param {string} string * @param {Object} trie * @param {Object} options * @param {string} options.endKey * @return {*} */ function get(string, trie, options) { if (!string || typeof string !== 'string') { return; } var endKey = options.endKey; var letters = string.split(''); var node = trie; for (var i = 0, len = letters.length, lastIndex = len - 1; i < len; i++) { var key = letters[i]; if (!node.hasOwnProperty(key)) { return; } node = node[key]; if (lastIndex === i && node.hasOwnProperty(endKey)) { return node[endKey]; } } } var get_1 = get; var assign = Object.assign; if (typeof assign !== 'function') { /** * Polyfills `Object.assign`. * * @see {@link https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign} * * @param {Object} target * @param {...Object} [source] * @return {Object} */ assign = function(target, source) { if (target === undefined || target === null) { throw new TypeError('Cannot convert undefined or null to object'); } for (var i = 1, len = arguments.length; i < len; i++) { if (i !== 1) { source = arguments[i]; } if (source instanceof Object) { for (var key in source) { target[key] = source[key]; } } } return target; }; } /** * Invokes function with arguments and data. * * @param {Function} func * @param {Array} args * @param {Object} data * @param {Object} options */ function invoke(func, args, data, options) { var argsLen = args.length; if (argsLen) { for (var i = 0; i < argsLen; i++) { func(args[i], data, options); } } } /** * Checks if object is empty. * * @param {Object} object * @return {boolean} */ function isObjectEmpty(object) { for (var key in object) { /* istanbul ignore else */ if (object.hasOwnProperty(key)) { return false; } } return true; } var utilities = { assign: assign, invoke: invoke, isObjectEmpty: isObjectEmpty }; var isObjectEmpty$1 = utilities.isObjectEmpty; /** * Removes string from trie (through object mutation). * * @param {string} string * @param {Object} trie * @param {Object} options * @param {string} options.endKey */ function remove(string, trie, options) { if (!string || typeof string !== 'string') { return; } var endKey = options.endKey; var letters = string.split(''); var node = trie; var nodes = [node]; for (var i = 0, len = letters.length, lastIndex = len - 1; i < len; i++) { var key = letters[i]; if (!node.hasOwnProperty(key)) { return; } node = node[key]; if (lastIndex === i && node.hasOwnProperty(endKey)) { delete node[endKey]; // clean up empty nodes like `{ a: {} }` while (isObjectEmpty$1(node)) { if (nodes.length) { // parent node node = nodes.pop(); // delete empty property delete node[letters[nodes.length]]; } else { break; } } } // keep track of traversed nodes nodes.push(node); } } var remove_1 = remove; var assign$1 = utilities.assign; var invoke$1 = utilities.invoke; /** * Constructs a trie. * * @constructor * @param {Object} [options] * @param {string} [options.endKey='$$'] * @param {number} [options.endValue=1] */ function Trie(options) { this.options = assign$1( { endKey: constants.END_KEY, endValue: constants.END_VALUE }, options ); this.data = {}; } /** * Adds string(s) to trie. * * @param {...string} * @return {this} */ Trie.prototype.add = function() { invoke$1(add_1, arguments, this.data, this.options); return this; }; /** * Checks if trie contains a string. * * @param {string} string * @return {boolean} */ Trie.prototype.contains = function(string) { return contains_1(string, this.data, this.options); }; /** * Gets end of string value from trie. * * @param {string} string * @return {*} */ Trie.prototype.get = function(string) { return get_1(string, this.data, this.options); }; /** * Removes string(s) from trie. * * @param {...string} * @return {this} */ Trie.prototype.remove = function() { invoke$1(remove_1, arguments, this.data, this.options); return this; }; var trie = Trie; /** * Instantiates a trie. * * @param {Object} [options] * @param {string} [options.endKey='$$'] * @param {number} [options.endValue=1] * @return {Trie} */ function trieste(options) { return new trie(options); } var trieste_1 = trieste; return trieste_1; }));