I have an array of objects with a "lv" property, which is always an integer greater than or equal to 0.
[
{lv: 0, name: "A"},
{lv: 1, name: "B"},
{lv: 1, name: "C"},
{lv: 2, name: "D"},
{lv: 3, name: "E"},
{lv: 1, name: "F"},
{lv: 0, name: "G"},
]
This data was exported from legacy software and represents a hierarchical tree structure. The "lv" property indicates the depth of each node in the tree relative to its parent node in the array. For instance, A is at level 0 (root); B is at level 1, making it a child of A; C is also level 1, making it a sibling of B and a child of A; and so on. This creates the following structure:
├ A
│ ├ B
│ ├ C
│ │ └ D
│ │ └ E
│ └ F
└ G
I am trying to write a function that can transform this flat array into a nested structure that better reflects the tree, like this:
[
{
name: "A",
children: [
{
name: "B",
children: null
},
{
name: "C",
children: [
{
name: "D",
children: [
{
name: "E",
children: null
}
]
}
]
},
{
name: "F",
children: null
}
]
},
{
name: "G",
children: null
}
]
In this structure, each node has an array of children under the "children" property, structured recursively.
I attempted to create a recursive function for this purpose, but it fails when encountering a node that moves up the tree (e.g., a level 1 node coming after a level 3 node). Here is the function I wrote:
function buildTree(arr) {
let siblings = [], children = null
while (arr.length) {
let node = arr.shift()
if (arr.length) {
let nodeLv = +node.lv
let nextNodeLv = +arr[0].lv
if (nextNodeLv > nodeLv) {
children = buildTree(arr)
}
}
let newNode = {
name: node.name,
children: children
}
siblings.push(newNode)
}
return siblings
}
However, instead of the desired structure, the function produces the following:
└ A
├ B
└ C
└ D
└ E
└ F
└ G
It seems to work correctly when building deeper levels, but struggles to handle backwards movements (like going from E to F or F to G).
What am I missing here? Is there a better approach to solving this problem?