key-tree
Version:
Simple keyed tree data structure
1 lines • 2.37 kB
JavaScript
(function(a,b){'object'==typeof exports&&'undefined'!=typeof module?module.exports=b():'function'==typeof define&&define.amd?define(b):a.KeyTree=b()})(this,function(){'use strict';class a{constructor(a,b,c){this.key=b||'',this.values=[],this.children=[],this.parent=a,this.appendValues(c)}get fullPath(){let a=[],b=this;for(;b;)a.splice(0,0,b.key),b=b.parent;return a}getChild(a){for(const b of this.children)if(a===b.key)return b;return null}ensureChild(b){let c=this.getChild(b);return c||(c=new a(this,b),this.children.push(c)),c}addChild(b,c){let d=this.getChild(b);return d?d.appendValues(c):(d=new a(this,b,c),this.children.push(d)),d}appendValues(a){if('undefined'!=typeof a){const b=Array.isArray(a)?a:[a];this.values=this.values.concat(b)}}}return class{constructor(b,c){if(this.sep=b&&b.separator||'.',this.$=new a,c)for(const a in c)this.add(a,c[a])}add(a,b){let c=this.$;if(''===a)return void c.appendValues(b);let d=(a||'').trim().split(this.sep);for(let e=0;e<d.length;e++)c=e===d.length-1?c.addChild(d[e],b):c.ensureChild(d[e])}_getNode(a){let b=this.$;if(''!==a){let c=(a||'').trim().split(this.sep);for(let a=0;a<c.length&&!!b;a++)b=b.getChild(c[a])}return b}get(a){const b=this._getNode(a);return b?b.values:[]}getSub(a,b){let c={grouped:{},ungrouped:[]};return this._reduce(a,this._getNode(a),c,!0),b?c.grouped:c.ungrouped}getSup(a,b){let c={grouped:{},ungrouped:[]};return this._reduce(a,this._getNode(a),c,!1),b?c.grouped:c.ungrouped}_reduce(a,b,d,e){if(b)if(d.grouped[a]=b.values,d.ungrouped=d.ungrouped.concat(b.values),e)for(const f of b.children){const b=`${a}${this.sep}${f.key}`;this._reduce(b,f,d,e)}else{const a=b.parent;if(a){const b=a.fullPath.join(this.sep);this._reduce(b,a,d,e)}}}remove(a,b){const c=this._getNode(a);let d=!1;if(c)for(;;){let a=-1;for(let d=0;d<c.values.length;d++)if(c.values[d]==b){a=d;break}if(0<=a)c.values.splice(a,1),d=!0;else break}return d}removeKey(a){if(a){const b=this._getNode(a);let c=!1;if(b){c=!0;const a=b.parent;let d=-1;for(let e,c=0;c<a.children.length;c++)if(e=a.children[c],e==b){d=c;break}0<=d&&a.children.splice(d,1)}return c}throw'Cannot remove the root key'}removeChildren(a){const b=this._getNode(a);return!!b&&(b.children=[],!0)}clearKey(a,b){const c=this._getNode(a);c&&this._clearNodeValues(c,b)}_clearNodeValues(a,b){if(a.values=[],b)for(const d of a.children)this._clearNodeValues(d,b)}}});