Search code examples
javascriptrecursion

Recursive function with nested tree not returning in 'order'


I have a data structure that contains nested arrays - I want to display the the data to make it look like a file structure - so nested data is represented as nested files / folders. However on console logging what the recursive function returns does not represent the nested nature of the data structure.

Here is my data structure:

const data = {
  "root": [
    {
      "type": "folder",
      "name": "one",
      "children": [
        {
          "type": "folder",
          "name": "one",
          "children": []
        },
        {
          "type": "file",
          "name": "two",
          "extension": ".txt",
          "preview": "photos.google.com/abc.jpg"
        },
        {
          "type": "file",
          "name": "four",
          "extension": ".txt",
          "preview": "photos.google.com/abc.jpg"
        }
      ]
    },
    {
      "type": "file",
      "name": "two",
      "extension": ".txt",
      "preview": "photos.google.com/abc.jpg"
    },
    {
      "type": "file",
      "name": "three",
      "extension": ".txt",
      "preview": "photos.google.com/abc.jpg"
    },
    {
      "type": "file",
      "name": "four",
      "extension": ".txt",
      "preview": "photos.google.com/abc.jpg"
    }
  ]
}

And my recursive function:

const recurse = (data, children = false) => {
  data.forEach(object => {
    if (object.type === 'folder') {
      recurse(object.children, true)
    }
    if (children) {
      console.log('   ' + object.type + ' ' + object.name);
    } else {
      console.log(object.type + ' ' + object.name);
    }
  })
}

recurse(data.root)

And the console log:

'   folder one'
'   file two'
'   file four'
'folder one'
'file two'
'file three'
'file four'

So the function is printing from the inside out of the structure. What approach should I be using if I want to display it in a way that reflects the nested nature of the data structure?


Solution

  • @j.xavier.atero was a bit faster than me. :)

    I think you have to put the recursion at the end of the function. That way you get the folder one first and then its children.

    const recurse = (data, children = false) => {
      data.forEach(object => {
        if (children) {
          console.log('   ' + object.type + ' ' + object.name);
        } else {
          console.log(object.type + ' ' + object.name);
        }
        if (object.type === 'folder') {
          recurse(object.children, true)
        }
      })
    }
    
    recurse(data.root)
    

    Update on comment

    I would say to add an extra argument for the recurse function so.

    const recurse = (data, level = 0) => {
      data.forEach(object => {
        console.log(Array(level).join('   ') + object.type + ' ' + object.name);
    
        if (object.type === 'folder') {
          recurse(object.children, level + 1)
        }
      })
    }
    
    recurse(data.root)
    

    This keeps track of the deepness of the recursive function. You don't even need the check if it's children anymore.