Skip to content

Commit f86692c

Browse files
committed
feat(tree): add tree building utility
1 parent e1af8cd commit f86692c

2 files changed

Lines changed: 39 additions & 0 deletions

File tree

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export * from './common';
22
export * from './string';
33
export * from './storage';
4+
export * from './tree';
45

56
export type * from './types';

src/tree.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
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

Comments
 (0)