|
| 1 | +type BaseNode<K extends string, P extends string> = { |
| 2 | + [key in K]: string | number; |
| 3 | +} & { |
| 4 | + [key in P]?: string | number | null; |
| 5 | +}; |
| 6 | + |
| 7 | +type BaseTreeNode<K extends string, P extends string, T extends BaseNode<K, P>> = T & { |
| 8 | + children?: Array<BaseTreeNode<K, P, T>>; |
| 9 | +}; |
| 10 | + |
| 11 | +export const buildTree = <K extends string, P extends string, T extends BaseNode<K, P>>( |
| 12 | + flatNodes: T[], |
| 13 | + key: K, |
| 14 | + parentKey: P |
| 15 | +) => { |
| 16 | + const map = new Map<string | number, BaseNode<K, P>>(); |
| 17 | + const tree: Array<BaseTreeNode<K, P, T>> = []; |
| 18 | + |
| 19 | + for (const node of flatNodes) { |
| 20 | + const current = (map.get(node[key]) || { ...node }) as BaseTreeNode<K, P, T>; |
| 21 | + Object.assign(current, node); |
| 22 | + map.set(node[key], current); |
| 23 | + |
| 24 | + if (node[parentKey] === null || node[parentKey] === undefined) { |
| 25 | + tree.push(current); |
| 26 | + } else { |
| 27 | + const parent = (map.get(node[parentKey]) || { ...current, [key]: node[parentKey] }) as BaseTreeNode<K, P, T>; |
| 28 | + |
| 29 | + if (!parent.children) { |
| 30 | + parent.children = []; |
| 31 | + } |
| 32 | + parent.children.push(current); |
| 33 | + map.set(node[parentKey], parent); |
| 34 | + } |
| 35 | + } |
| 36 | + |
| 37 | + return tree; |
| 38 | +}; |
0 commit comments