🍊

# > こういうフラットな配列から木構造を作るのってどうやったらいいんだろう？

2021/05/11に公開
``````interface Chapter {
level: number;
text: string;
}
interface ChapterNode extends Chapter {
children: ChapterNode[];
}
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" },
];
const treefy = (queue: Chapter[], level = 1): ChapterNode[] =>
queue.reduce(
(acc, cur, idx, array) =>
cur.level === level
? acc.concat({
...cur,
children: treefy(
takeWhile((c) => c.level >= level + 1, array.slice(idx + 1)),
level + 1
),
})
: acc,
[] as ChapterNode[]
);
const takeWhile = <T>(func: (head: T) => boolean, accum: T[]): T[] =>
accum.length && func(accum[0])
? [accum[0], ...takeWhile(func, accum.slice(1))]
: ([] as T[]);
console.log(JSON.stringify(treefy(input), null, 2));
``````
``````\$ deno run treefy.ts
[
{
"level": 1,
"text": "1章",
"children": []
},
{
"level": 1,
"text": "2章",
"children": [
{
"level": 2,
"text": "2.1",
"children": []
},
{
"level": 2,
"text": "2.2",
"children": []
}
]
},
{
"level": 1,
"text": "第3章",
"children": [
{
"level": 2,
"text": "3.1",
"children": []
},
{
"level": 2,
"text": "3.2",
"children": [
{
"level": 3,
"text": "3.2.1",
"children": []
},
{
"level": 3,
"text": "3.2.2",
"children": []
}
]
}
]
}
]
``````

Gist