type ItemTree = { data: any count: number children: Array }; function treeInit() : ItemTree { return {data:undefined, count:0, children:[]} } function treeNode(data : number, count : number) : ItemTree { return {data:data, count:count, children:[]} } /* * Merge a node with an item tree */ function nodeMerge(itemtree : ItemTree, node : ItemTree) { const item = node.data; const count = node.count; let next : ItemTree | null = null; // Try to find an existing node in this tree level with same item for(let node of itemtree.children) { if(node.data == item) { node.count += 1; next = node; break; } } // If not found, add item node at this level if(next == null) { next = treeNode(item, count) itemtree.children.push(next) } return next; } /* * Merge a full build path with an existing item tree */ function treeMerge(itemtree : ItemTree, items : Array) { let current = itemtree; for(let item of items) { current = nodeMerge(current, {data: item, count:1, children:[]}) } } function treeCutBranches(itemtree : ItemTree, thresholdCount : number, thresholdPerc : number) { // Remove branches that are above threshold count while(itemtree.children.length > thresholdCount) { let leastUsedBranch = itemtree.children.reduce((a, b) => Math.min(a.count, b.count) == a.count ? a : b, {data:undefined, count: +Infinity, children: []}) itemtree.children.splice(itemtree.children.indexOf(leastUsedBranch), 1) } // Remove branches that are of too low usage let toRemove : Array = [] for(let child of itemtree.children) { if((child.count/itemtree.count) < thresholdPerc) { toRemove.push(child) } } for(let tr of toRemove) { itemtree.children.splice(itemtree.children.indexOf(tr), 1) } itemtree.children.map((x) => treeCutBranches(x, thresholdCount, thresholdPerc)) } function treeMergeTree(itemtree1: ItemTree, itemtree2: ItemTree) { for(let child of itemtree2.children) { let node = nodeMerge(itemtree1, child) treeMergeTree(node, child) } } function treeSort(itemtree: ItemTree) { itemtree.children.sort((a, b) => b.count - a.count) for(let item of itemtree.children) { treeSort(item) } } export {ItemTree, treeMerge, treeInit, treeCutBranches, treeSort}