🍊
> こういうフラットな配列から木構造を作るのってどうやったらいいんだろう?
Of https://twitter.com/suin/status/1390626681547751429
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": []
}
]
}
]
}
]
Discussion