javascriptarraystreetree-structure

flatten tree structure into array


I have this tree structure:

    data = 
    {
     [
       {
        type: "folder"
        name: "animals"
        path: "/animals"
        children  :
          [
            {
            type: "folder"
            name: "cat"
            path: "/animals/cat"
            children:
              [
                {
                  type: "folder"
                  name: "images"
                  path: "/animals/cat/images"
                  children: 
                    [
                      {
                        type: "file"
                        name: "cat001.jpg"
                        path: "/animals/cat/images/cat001.jpg"
                      },
                      {
                        type: "file"
                        name: "cat001.jpg"
                        path: "/animals/cat/images/cat002.jpg"
                      }
                    ]
                }
              ]
            }
        ]
      }
    ]
}

I want to turn it into

[
  {
    type: "folder"
    name: "animals"
    path: "/animals"
  },
  {
    type: "folder"
    name: "cat"
    path: "/animals/cat"
  },
  {
    type: "folder"
    name: "images"
    path: "/animals/cat/images"
  },
  {
    type: "file"
    name: "cat001.jpg"
    path: "/animals/cat/images/cat001.jpg"
  },
  {
    type: "file"
    name: "cat001.jpg"
    path: "/animals/cat/images/cat002.jpg"
  }
]

I came up with this function, but seems does not work

    function flatten(nodes, flattedNodes) {
      for (let index = 0; index < nodes.length; index++) {
        flattedNodes.push(nodes[index]);
        if (nodes[index].children !== undefined)
        if (nodes[index].children.length > 0)
          flatten(nodes[index].children, flattedNodes);
      }
    }

  let flattedTree = [];
  flatten(data, flattedTree);

  console.log(JSON.stringify(flattedTree, null, 4));

It does not flatten some elements. Any ideas how to fix?


Solution

  • Here's a solution using flatMap() and recursion:

    const flatten = (array) => array.flatMap(({ type, name, path, children }) => [
      { type, name, path },
      ...flatten(children || [])
    ]);
    

    Complete snippet:

    const data = [{
      type: "folder",
      name: "animals",
      path: "/animals",
      children: [{
        type: "folder",
        name: "cat",
        path: "/animals/cat",
        children: [{
          type: "folder",
          name: "images",
          path: "/animals/cat/images",
          children: [{
              type: "file",
              name: "cat001.jpg",
              path: "/animals/cat/images/cat001.jpg"
            }, {
              type: "file",
              name: "cat001.jpg",
              path: "/animals/cat/images/cat002.jpg"
            }
          ]
        }]
      }]
    }];
    
    const flatten = (array) => array.flatMap(({type, name, path, children}) => [
      { type, name, path },
      ...flatten(children || [])
    ]);
    
    console.log(flatten(data));