Skip to content

Instantly share code, notes, and snippets.

@Hongyu-Zhuo
Last active December 11, 2020 05:55
Show Gist options
  • Save Hongyu-Zhuo/ff59dc3c40f75d5b88c084a4c72fef67 to your computer and use it in GitHub Desktop.
Save Hongyu-Zhuo/ff59dc3c40f75d5b88c084a4c72fef67 to your computer and use it in GitHub Desktop.
Flat data array converted to tree data
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