2

I want to create a folder tree using a list of objects that contain paths. This solution is working only for a list of strings(paths), but I don't know how to make it work using objects.

    var paths = ["About.vue", "Categories/Index.vue", "Categories/Demo.vue", "Categories/Flavors.vue", "Categories/Types/Index.vue", "Categories/Types/Other.vue"],
            result = paths.reduce((r, p) => {
              var names = p.split("/");
              names.reduce((q, name) => {
                var temp = q.find(o => o.name === name);
                if (!temp) {
                  q.push((temp = { name, children: [] }));
                }
                return temp.children;
              }, r);
              return r;
            }, []);

            console.log(result)

I want to do the same but instead of using an array of paths using an array of objects that contains paths.

From an array like this:

var paths = [{
  path: "/media",
  id: 9,
  name:"media"
},{
  path: "/media/folder1",
  id: 1,
  name:"folder1"
},{
  path: "/media/folder1/child",
  id: 3,
  name: "child"
},
{
  path: "/media/folder2",
  id: 2,
  name: "folder2"
}];

I want something like this:

 [
  {
    "id": 9,
    "name": "media",
    "children": [
      {
        "id": 1,
        "name": "folder1",
        "children": [
          {
            "id": 3,
            "name": "child",
            "children": []
          }
        ]
      },
      {
        "id": 2,
        "name": "folder2",
        "children": []
      }
    ]
  }
]
5
  • Your input and expected output don't match (input root folder is media, output root folder is applications etc.). Can you either change the input or the output so that they match, please? Then I can ensure I give you the correct output for a given input. Commented Jun 14, 2020 at 20:57
  • The output is just an example of what I want, the real output is in the code snippet I made @AlexL Commented Jun 14, 2020 at 21:05
  • Yeah ok, but the point is, a good question has a stated input and a stated expected output. So in your case, keep it consistent and choose one input to reference and one matching output to reference, make sense? stackoverflow.com/help/minimal-reproducible-example Commented Jun 14, 2020 at 21:07
  • @AlexL output updated Commented Jun 14, 2020 at 21:30
  • Perfect 👌 and my answer gives this output :) Commented Jun 14, 2020 at 21:33

1 Answer 1

2

If you want to use the example code you gave, you just need to change one line:

const [root, ...names] = p.path.split("/");

and add another line:

const id = p.name == name ? p.id : undefined;

and change one final line:

q.push((temp = { id, name, children: [] }));

const paths = ["About.vue", "Categories/Index.vue", "Categories/Demo.vue", "Categories/Flavors.vue", "Categories/Types/Index.vue", "Categories/Types/Other.vue"];

const paths2 = [
  {
  path: "/media",
  id: 9,
  name:"media"
},{
  path: "/media/folder1",
  id: 1,
  name:"folder1"
},{
  path: "/media/folder1/child",
  id: 3,
  name: "child"
},
{
  path: "/media/folder2",
  id: 2,
  name: "folder2"
}];

const out1 = createTree(paths);
const out2 = createTree(paths2);

function createTree(input){
  const result = input.reduce((r, p, i) => {
    if (!(p instanceof Object)){
      p = {path: p, id: i};
    }
    const path = p.path && p.path.substr(0,1) == "/"
                ? p.path
                : "/" + p.path;
    const [root, ...names] = path.split("/");
    const last = names[names.length - 1];
    names.reduce((q, name) => {
      let temp = q.find(o => o.name === name);
      //const id = p.name == name ? p.id : undefined;
      const id = last == name ? p.id : undefined
      if (!temp) {
        q.push((temp = { id, name, children: [] }));
      }
      return temp.children;
    }, r);
    return r;
  }, []);
  console.log(result)
  return result;
}

Output:

[
  {
    "id": 9,
    "name": "media",
    "children": [
      {
        "id": 1,
        "name": "folder1",
        "children": [
          {
            "id": 3,
            "name": "child",
            "children": []
          }
        ]
      },
      {
        "id": 2,
        "name": "folder2",
        "children": []
      }
    ]
  }
]
Sign up to request clarification or add additional context in comments.

8 Comments

But after modifying that how can I get the id from the object in the q.push((temp = { name, children: [] })); method?
I made the changes needed to include the id in my updated answer, does that work?
No, this is not working, it only adds the id to the last childs of the tree, the rest are showing undefined values
The only undefined it assigns is to {name: "media"} because from your data, how am I supposed to know what id that has? Should i generate it randomly? All other items have the correct id, right?
Even adding the /media route to the array It gives undefined value for some reason. I tested the code here link
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.