I want to convert an array with this shape into a nested object shape.
I've been thinking about it for hours, but I can't come up with a proper way. Any good way?
before
let files2 = [
"folder/empty_file.txt",
"folder/inner file.txt",
"user16.txt",
"reagjjjd.md",
"folder/folder2/hi.txt",
];
after
let files = [
{ folder: [{ folder2: ["hihi.txt"] }, "empty_file.txt", "inner file.txt"] },
"user16.txt",
"reagjjjd.md",
];
I would appreciate any help or guidance here. Thanks!
Here is a solution that can convert arbitrary folder depth into a tree according to your requirement. It basically builds the tree through text splitting and recursion, which works but is likely not ideal. I wish it were a little simpler, but hopefully it helps if no-one else offers a better solution.
// const path = require("path");
// const sep = path.sep;
const sep = "/";
const input = [
"folder/empty_file.txt",
"folder/inner file.txt",
"user16.txt",
"reagjjjd.md",
"folder/folder2/hi.txt",
];
const get_files = (list) => {
return list.filter((s) => s.length < 2).map((s) => s[0]);
};
const get_folder_names = (list) => {
return [...new Set(list.filter((s) => s.length > 1).map((s) => s[0]))];
};
const get_folder_contents = (list, folder) => {
return list
.filter((s) => s.length > 1)
.filter((s) => s[0] == folder)
.map((s) => s.slice(1));
};
const get_folders = (list) => {
return get_folder_names(list).map((folder) => {
return { [folder]: build_tree(get_folder_contents(list, folder)) };
});
};
function build_tree(list) {
const tree = [];
tree.push(...get_files(list));
tree.push(...get_folders(list));
return tree;
}
const list = input.map((s) => s.split(sep));
const output = build_tree(list);
console.log("Tree:", JSON.stringify(output));
newArr by your structure .
newArr1 by my structure suggest
let files = [
"folder/empty_file.txt",
"folder/inner file.txt",
"user16.txt",
"reagjjjd.md",
"folder/folder2/hi.txt",
]
let newArr = files.reduce((res, path) => {
let convertArr = path.split("/")
if(convertArr.length < 2) return [...res, path]
let parent = res
let treePath = convertArr.forEach( (ele, key) => {
let temParent = parent.find(el => typeof el === 'object' && el.hasOwnProperty(ele))
if (temParent) {
parent = temParent[ele]
} else {
let tmp = key === convertArr.length-1 ? ele : {[ele] : []}
parent.push(tmp)
parent = tmp[ele]
}
})
return res
}, [])
let files2 = [
"folder/empty_file.txt",
"folder/inner file.txt",
"user16.txt",
"reagjjjd.md",
"folder/folder2/hi.txt",
]
let newArr1 = files2.reduce((res, path) => {
let convertArr = path.split("/")
let parent = res
let treePath = convertArr.forEach( ele => {
let temParent = parent.find(el => el.path === ele)
if (!temParent) {
let tmp = {path: ele, children: []}
parent.push(tmp)
parent = tmp.children
} else {
parent = temParent.children
}
})
return res
}, [])
console.log(newArr)
console.log(newArr1)
I think the array structure should follow this format for ease of use :
[
{
path : 'folder',
children : [
{
path : 'empty_file.txt',
children : []
},
{
path : 'inner file.txt',
children : []
},
{
path : 'folder2',
children : [
{
path : 'hi.txt',
children : []
}
]
},
]
},
{
path : 'user16.txt',
children : []
},
{
path : 'reagjjjd.md',
children : []
}
]