Last active
December 11, 2020 05:55
-
-
Save Hongyu-Zhuo/ff59dc3c40f75d5b88c084a4c72fef67 to your computer and use it in GitHub Desktop.
Flat data array converted to tree data
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| export class TreeUtil<T extends TreeNode<T>> { | |
| map: {[k: string]: number} = {}; | |
| roots: T[] = []; | |
| /** | |
| * @field status | |
| * @type | |
| * 0 - 未成功执行 `config` 方法; | |
| * 1 - 已成功执行 `config` 方法; | |
| */ | |
| status: 0 | 1 = 0; | |
| pIdField!: keyof T; | |
| childIdField!: keyof T; | |
| levelIdField!: keyof T; | |
| constructor() {} | |
| /** | |
| * @function config - 配置字段名称 | |
| * @param pIdField - parent id 对应的字段 | |
| * @param childIdField - 节点 id 对应的字段 | |
| * @param levelIdField - 节点 level 对应的字段 | |
| * @example | |
| * ``` ts | |
| * T = { | |
| * pId: 0, | |
| * id: 1 | |
| * } | |
| * ``` | |
| * 则 `pIdField` 值为 ‘pId’, `childIdField` 的值为 1 | |
| */ | |
| config(pIdField: any, childIdField: any, levelIdField?: any): this { | |
| this.pIdField = pIdField; | |
| this.childIdField = childIdField; | |
| this.levelIdField = levelIdField; | |
| this.status = 1; | |
| return this; | |
| } | |
| /** | |
| * @function toTree | |
| * @param list - 源数据 | |
| * @param isSorted 是否是已根据 level 排序(祖先节点在前)的数据 | |
| * @description | |
| * 如果是已排序数据,则合并两次循环 | |
| * @link https://stackoverflow.com/questions/18017869/build-tree-array-from-flat-array-in-javascript/22072374 | |
| */ | |
| toTree(list: T[], isSorted = false): T[] { | |
| if (this.status === 0) { | |
| throw new Error('Please execute config method first!'); | |
| } | |
| // list.sort((a, b) => (a[this.levelIdField] as any) - b[this.levelIdField]); | |
| if (isSorted) { | |
| list.forEach((node, index) => { | |
| this.initMap(node, index); | |
| this.addChildNode(this.roots, list, node); | |
| }); | |
| } else { | |
| list.forEach(this.initMap.bind(this)); | |
| list.forEach((node, index) => { | |
| this.addChildNode(this.roots, list, node); | |
| }); | |
| } | |
| return JSON.parse(JSON.stringify(this.roots)); | |
| } | |
| initMap(node: T, index: number): void { | |
| this.map[node.id] = index; | |
| node.children = []; | |
| } | |
| addChildNode(target: T[], sources: T[],childNode: T): void { | |
| if (childNode[this.pIdField] !== 0) { | |
| sources[this.map[childNode.pId]].children.push(childNode); | |
| } else { | |
| target.push(childNode); | |
| } | |
| } | |
| } | |
| interface TreeNode<U> { | |
| [k: string]: any; | |
| children: U[]; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment