flatten tree structure into array

1.3k views Asked by At

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?

1

There are 1 answers

0
Robby Cornelissen On BEST ANSWER

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));