Reputation: 972
I did find this question How to convert an array of paths into JSON structure? but, I can't seem to manipulate the answer to achieve what I want.
I have an array of Paths that I want to turn into an object that can be easily used on the client.
[
"\\Folder\file.xlsx",
"\\Folder\file2.xlsx",
"\\Folder\file3.docx",
"\\Folder\Folder2\file4.xlsx",
"\\Folder\Folder2\Folder3\file5.xlsx",
"\\Folder\Folder2\file6.xlsx",
"\\Folder\Folder4\file7.pdf"
"\\Folder\Folder4\Folder5\1. file8.pdf"
]
I'm trying to get an output that looks something like this:
output = {
Folder: {
{
file: file.xlsx,
path: \\Folder\file.xlsx
},
{
file: file2.xlsx,
path: \\Folder\file2.xlsx
},
{
file: file3.xlsx,
path: \\Folder\file3.docx
}
Folder2: {
{
file: file4.xlsx,
path: \\Folder\Folder2\file4.xlsx
},
Folder3:{
{
file: file5.xlsx,
path: \\Folder\Folder2\Folder3\file5.xlsx
},
},
{
file: file6.docx,
path: \\Folder\Folder2\file6.xlsx
}
},
Folder4: {
{
file: file7.pdf,
path: \\Folder\Folder4\file7.pdf
},
Folder5: {
{
file: 1. file8.pdf,
path: \\Folder\Folder4\Folder5\1. file8.pdf
},
}
}
}
}
currently, I have this which gives me empty objects but no path:
var output = {};
var current;
for (var a = 0; a < files.length; a++) {
var s = files[a].split("\\");
// console.log("s ===> ", s);
current = output;
for (var i = 0; i < s.length; i++) {
if (s[i] != "") {
if (current[s[i]] == null) {
current[s[i]] = {};
} else {
current = current[s[i]];
}
}
}
}
But it doesn't return quite what I am looking for. I'm not entirely sure if there are functions like map or reduce that can help with this as I'm quite new to Javascript.
If someone could point me in the right direction that would be great.
Upvotes: 1
Views: 99
Reputation: 2621
This will work recursively so you can go deeper like \\Folder\\........\\Folder10\\file.doc
;
const files = [
"\\Folder\\file.xlsx",
"\\Folder\\file2.xlsx",
"\\Folder\\file3.docx",
"\\Folder\\Folder2\\file4.xlsx",
"\\Folder\\Folder2\\Folder3\\file5.xlsx",
"\\Folder\\Folder2\\file6.xlsx",
"\\Folder\\Folder4\\file7.pdf",
"\\Folder\\Folder4\\Folder5\\1. file8.pdf"
];
const result = files.reduce((obj, p) => {
let temp = obj;
p.split('\\').forEach((d, i, arr) => {
if (!d) return;
if (i === 0) return;
if (i === arr.length - 1) {
temp['files'] = [...(temp['files'] || []), {
file: d,
path: p
}];
} else if (!temp[d]) {
temp[d] = {};
}
temp = temp[d];
});
return obj;
}, {});
console.log(result);
Direct files of a folder are in files
array.
{
"Folder": {
"files": [
{
"file": "file.xlsx",
"path": "\\Folder\\file.xlsx"
},
{
"file": "file2.xlsx",
"path": "\\Folder\\file2.xlsx"
},
{
"file": "file3.docx",
"path": "\\Folder\\file3.docx"
}
],
"Folder2": {
"files": [
{
"file": "file4.xlsx",
"path": "\\Folder\\Folder2\\file4.xlsx"
},
{
"file": "file6.xlsx",
"path": "\\Folder\\Folder2\\file6.xlsx"
}
],
"Folder3": {
"files": [
{
"file": "file5.xlsx",
"path": "\\Folder\\Folder2\\Folder3\\file5.xlsx"
}
]
}
},
"Folder4": {
"files": [
{
"file": "file7.pdf",
"path": "\\Folder\\Folder4\\file7.pdf"
}
],
"Folder5": {
"files": [
{
"file": "1. file8.pdf",
"path": "\\Folder\\Folder4\\Folder5\\1. file8.pdf"
}
]
}
}
}
}
Upvotes: 1
Reputation: 5960
Here is an example with map
and reduce
:)
Watch out, your expected output is not valid, so i've adjusted a bit to what seems the most natural.
const files = [
"\\Folder\\file.xlsx",
"\\Folder\\file2.xlsx",
"\\Folder\\file3.docx",
"\\Folder\\Folder2.xlsx",
"\\Folder\\Folder2\\file4.xlsx",
"\\Folder\\Folder3\\file5.xlsx",
"\\Folder\\Folder3\\file6.docx",
"\\Folder\\Folder4\\file7.pdf"
];
const result = files.map(filePath =>
({
path: filePath,
file: filePath.substring(filePath.lastIndexOf('\\')+1)
})).reduce((acc, item) => {
const folderPath = item.path.substring(0, item.path.length-(item.file.length+1));
const folder = folderPath.substring(folderPath.lastIndexOf('\\')+1);
acc[folder] = acc[folder] || [];
acc[folder].push(item);
return acc;
}, {});
console.log(result);
Here is a small explanation:
First, you map
your files to the expected objects, then, you re-organize them with reduce
! You pipe both map
and reduce
and it is doing the job!
Upvotes: 3