🐕
フラットな配列から木構造を作る
const input = [
{ level: 1, text: '1章' },
{ level: 1, text: '2章' },
{ level: 2, text: '2.1' },
{ level: 2, text: '2.2' },
{ level: 1, text: '第3章' },
{ level: 2, text: '3.1' },
{ level: 2, text: '3.2' },
{ level: 3, text: '3.2.1' },
{ level: 3, text: '3.2.2' },
]
type TreeNode<I> = Omit<I, 'children'> & { children?: TreeNode<I>[] }
type Input<I> = (I & { children: unknown })[]
const treefy = <I extends { level: number }>(input: I[]) => {
const tree: TreeNode<I>[] = []
const last: TreeNode<I>[] = []
let top = -1
let bottom = -1
for (const { children: _, ...item } of input as Input<I>) {
if (top < item.level && item.level <= bottom + 1) {
const idx = item.level - top
bottom = item.level
;(last[idx - 1].children ??= []).push(item)
last[idx] = item
continue
}
tree.push(item)
last[0] = item
top = bottom = item.level
}
return tree
}
const output = treefy(input)
console.log(JSON.stringify(output, null, 2))
解説
for 文のネストや array#pop などを使用しないことで軽量になっていると思います。
level が一度に 2 以上増えないという前提で書いているのでそれが壊れるとこれも壊れます。
Discussion