Search code examples
javascriptarraysobjectindentation

Transform data from flat into a nested tree structure based on value of indent attribute


We have an array similar to this:

const pages= [
{
  "name": "Hello World",
  "code": "hello-world",
  "indent": 0,
  "subpages": null
},
{
  "name": "What is going on?",
  "code": "what-is-going-on",
  "indent": 1,
  "subpages": null
},
{
  "name": "My Page",
  "code": "my-page",
  "indent": 0,
  "subpages": null
}
  ]

And we want to nest it so it looks like this:

  "data": {
"hello-world": {
  "name": "Hello World",
  "subpages": {
    "what-is-going-on": {
      "name": "What is going on?",
      "subpages": {}
    }
  }
},
"my-page": {
  "name": "My Page",
  "subpages": {}
}}}

So far, I was able to make it work, but it fails when there are MORE OBJECTS with GREATER INDENTS, or just more indents greater than 1 in a row. This is the code I came up with

var arr = []
for (let i=0; i<pages.length; i++) {
  
if (pages[i].indent==0) {
  arr.push(pages[i]);
}
else {
    arr[i-1].children=pages[i]
}
}

Its hard to admit it, but I feel like this approach will not work with more data - greater indents. I don't really know where should my solution be heading from. What do you think would work? Thank you for your time.


Solution

  • You could do this using reduce method and use an array to keep indent levels.

    const pages = [{"name":"Hello World","code":"hello-world","indent":0,"subpages":null},{"name":"What is going on?","code":"what-is-going-on","indent":1,"subpages":null},{"name":"My Page","code":"my-page","indent":0,"subpages":null}]
    
    const result = {}
    const levels = [result]
    
    pages.reduce((r, {name, code, indent}) => {
      const subpages = {}
      r[indent][code] = {name, subpages}
      r[indent + 1] = subpages
      
      return r
    }, levels)
    
    console.log(result)