0

I have an array of JSON objects which is something like:

var fileArray = [
  { name: "file1", path: "/main/file1" },
  { name: "file2", path: "/main/folder2/file2" },
  { name: "file4", path: "/main/folder3/file4" },
  { name: "file5", path: "/main/file5" },
  { name: "file6", path: "/main/file6" }
];  

What I want it to look like eventually is:

fileTree = [
  {
    "name": "file1",
    "children": []
  },
  {
    "name": "folder1"
    "children": [
      {
        "name": "folder2",
        "children": [
          {
            "name": "file2",
            "children": []
          }
        ]
      },
      {
        "name": "folder3",
        "children": [
          {
            "name": "file4",
            "children": []
                }
              ]
            }
          ]
        },
  {
    "name": "file5",
    "children": []
        },
  {
    "name": "file6",
    "children": []
  }
];

I tried the solution mentioned in Create a nested UL menu based on the URL path structure of menu items but the first comment to the first answer is exactly the problem I am having. All help is appreciated.

4
  • 5
    where does folder1 come from, also why would a file have a children property, albeit empty. Commented Jun 1, 2017 at 13:17
  • 1
    I have a JSON object array not if it looks like that you don't Commented Jun 1, 2017 at 13:17
  • 2
    Why don't you include the linked snippet you've tried in this question and demonstrate the problem/edge case that doesn't work? For certain, somebody is going to write the code for you, but I'm not sure if you'll learn much from that... Commented Jun 1, 2017 at 13:24
  • James, The folder names are just for reference. George, What I mean is I have an array of JSON objects. I am new to this, so pardon my errors. Commented Jun 2, 2017 at 10:05

2 Answers 2

2

You could use a nested hash table as reference to the same directories and build in the same way the result set.

var fileArray = [{ name: "file1", path: "/main/file1" }, { name: "file2", path: "/main/folder2/file2" }, { name: "file4", path: "/main/folder3/file4" }, { name: "file5", path: "/main/file5" }, { name: "file6", path: "/main/file6" }],
    temp = [],
    fileTree;

fileArray.forEach(function (hash) {
    return function (a) {
        a.path.replace('/', '').split('/').reduce(function (r, k) {
            if (!r[k]) {
                r[k] = { _: [] };
                r._.push({ name: k, children: r[k]._ });
            }
            return r[k];
        }, hash);
    };
}({ _: temp }));

fileTree = temp[0].children;
console.log(fileTree);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks a lot Nina! This did the trick for me with a little modification.
maybe you consider to use for the path only directories and not the file itself, then you could assign the filename without reference to the inner object, by appending the reduce expression with ... }, hash)._.push({ name: a.name });
I am using the result of this to display the file structure of an uploaded folder and so I need the path of the files and folders.
@raviabhiram, you may have a look here: What should I do when someone answers my question?
0

This won't give the exact result you want but I think it's usable:

var fileArray = [
  { name: "file1", path: "/main/file1" },
  { name: "file2", path: "/main/folder2/file2" },
  { name: "file4", path: "/main/folder3/file4" },
  { name: "file5", path: "/main/file5" },
  { name: "file6", path: "/main/file6" }
];  

var tree = fileArray.reduce(function (b, e) {
  var pathbits = e.path.split("/");
  var r = b;
  for (var i=1; i < pathbits.length - 1; i++) {
    bit = pathbits[i];
    if (!r[bit]) r[bit] = {};
    r = r[bit];
  }
  if (!r.files) r.files = [];
  r.files.push(e.name);
  return b;
}, {});

console.log(tree);

1 Comment

Thanks for your help James, but I later need to use the result to render a html page for which I use a library and that's why I need the result to look exactly like I mentioned.

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.