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.
asked Jun 1, 2017 at 13:14
raviabhiram
7302 gold badges9 silver badges23 bronze badges
-
5where does folder1 come from, also why would a file have a children property, albeit empty.James– James2017年06月01日 13:17:26 +00:00Commented Jun 1, 2017 at 13:17
-
1I have a JSON object array not if it looks like that you don'tGeorge– George2017年06月01日 13:17:43 +00:00Commented Jun 1, 2017 at 13:17
-
2Why 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...user3297291– user32972912017年06月01日 13:24:46 +00:00Commented 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.raviabhiram– raviabhiram2017年06月02日 10:05:42 +00:00Commented Jun 2, 2017 at 10:05
2 Answers 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; }
answered Jun 1, 2017 at 13:37
Nina Scholz
388k26 gold badges367 silver badges417 bronze badges
Sign up to request clarification or add additional context in comments.
4 Comments
raviabhiram
Thanks a lot Nina! This did the trick for me with a little modification.
Nina Scholz
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 });raviabhiram
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.
Nina Scholz
@raviabhiram, you may have a look here: What should I do when someone answers my question?
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);
answered Jun 1, 2017 at 13:42
James
22.4k5 gold badges30 silver badges44 bronze badges
1 Comment
raviabhiram
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.
lang-js