UNPKG

typescript-util

Version:

JS/TS 的简单工具

128 lines 4.28 kB
import { ArrayTool } from './ArrayTool'; /** * TreeTool * @author 冰凝 * @date 2022-09-19 09:45:27 **/ export class TreeTool { /** * 根据指定子节点, 递归寻找所在树中 从根节点到指定节点路径上所有节点 * @template {Constructor<{}>} NODE * @param data {NODE | NODE[]}树 * @param currentNode {NODE} 目标节点 * @param id {string} 判断是否相等的属性名, 默认 id * @param child {string} 子节点属性名, 默认 children * @return {NODE[]} */ static treePath(data, currentNode, id = 'id', child = 'children') { const pathArr = []; let find = false; const recursionTree = (treeData) => { if (find) { return; } // 数组 if (Array.isArray(treeData)) { for (const treeDataItem of treeData) { recursionTree(treeDataItem); if (find) { return; } } return; } // 对象 // @ts-ignore if (treeData[id] === currentNode[id]) { find = true; pathArr.push(treeData); return; } // 树节点 // @ts-ignore const childList = treeData[child]; if (Array.isArray(childList) && childList.length > 0) { for (const c of childList) { // 深度 +1 pathArr.push(treeData); recursionTree(c); if (find) { return; } else { pathArr.pop(); } } } }; recursionTree(data); return pathArr; } /** * 树结构遍历 * @param treeArr 源树结构数组 * @param map 需要对节点元素执行操作的映射器 * @param {[] | null} emptyChildren 空子节点使用什么值代替, 默认 [] * @param children Children 属性名, 默认 children * @returns 映射器返回的结果的数组 */ static treeEach(treeArr, map, emptyChildren = [], children) { if (ArrayTool.isEmpty(treeArr)) { return emptyChildren; } return treeArr.map(i => { const propertyName = children || 'children'; // @ts-ignore if (this.isNotEmpty(i[propertyName])) { // @ts-ignore i[propertyName] = this.treeEach(i[propertyName], map, emptyChildren, children); } return map(i); }); } /** * 构建树结构 * @param treeList 展开的节点列表 * @param filterRoot 过滤根节点的策略 * @param idKey ID 属性名 * @param pidKey parentId 属性名 * @param childrenKey children 列表 属性名 * @param leaveEmptyChildren 是否保留空的子节点, 默认不保留 */ static buildTree(treeList, filterRoot, idKey, pidKey, childrenKey, leaveEmptyChildren = false) { if (ArrayTool.isEmpty(treeList)) { return []; } // Id -> 节点映射 const mapping = treeList.reduce((pv, cv) => { pv[cv[idKey]] = cv; return pv; }, {}); for (let node of treeList) { const pid = node[pidKey]; if (pid === undefined) { continue; } const pNode = mapping[pid]; if (pNode === undefined || pNode === null) { continue; } if (ArrayTool.isEmpty(pNode[childrenKey])) { pNode[childrenKey] = []; } pNode[childrenKey].push(node); } // @ts-ignore let root = Object.values(mapping).filter(filterRoot); if (!leaveEmptyChildren) { root = ArrayTool.treeEach(root, i => { if (ArrayTool.isEmpty(i[childrenKey])) { delete i[childrenKey]; } return i; }, undefined, childrenKey); } return root; } } //# sourceMappingURL=TreeTool.js.map