I have a directory structure from NPM package 'directory-tree' that I would like to flatten into a simpler nested structure. I want a tail recursive solution to convert the first object into the second, but I'm having trouble wrapping my head around how to construct it.
Of course the primary conditional is whether or not a 'node' in the first structure is a 'file' or a 'directory'. If it's a file, we simply want the basename of the file to key the relative path. However, if it's a directory, we want the basename of the directory to key an object and recurse down frome there.
I'll use their example to illustrate the structure:
{
"path": "photos",
"name": "photos",
"size": 600,
"type": "directory",
"children": [
{
"path": "photos/summer",
"name": "summer",
"size": 400,
"type": "directory",
"children": [
{
"path": "photos/summer/june",
"name": "june",
"size": 400,
"type": "directory",
"children": [
{
"path": "photos/summer/june/windsurf.jpg",
"name": "windsurf.jpg",
"size": 400,
"type": "file",
"extension": ".jpg"
}
]
}
]
},
{
"path": "photos/winter",
"name": "winter",
"size": 200,
"type": "directory",
"children": [
{
"path": "photos/winter/january",
"name": "january",
"size": 200,
"type": "directory",
"children": [
{
"path": "photos/winter/january/ski.png",
"name": "ski.png",
"size": 100,
"type": "file",
"extension": ".png"
},
{
"path": "photos/winter/january/snowboard.jpg",
"name": "snowboard.jpg",
"size": 100,
"type": "file",
"extension": ".jpg"
}
]
}
]
}
]
}
I'd like the final structure to be much simpler. Something like the following:
{
"photos": {
"summer": {
"june": {
"windsurf.jpg": "photos/summer/june/windsurf.jpg"
}
},
"winter": {
"january": {
"ski.png": "photos/winter/january/ski.png",
"snowboard.jpg": "photos/winter/january/snowboard.jpg"
}
}
}
}
We can convert a depth-first search to tail-recursion for your case.
let testObj = {
"path": "photos",
"name": "photos",
"size": 600,
"type": "directory",
"children": [
{
"path": "photos/summer",
"name": "summer",
"size": 400,
"type": "directory",
"children": [
{
"path": "photos/summer/june",
"name": "june",
"size": 400,
"type": "directory",
"children": [
{
"path": "photos/summer/june/windsurf.jpg",
"name": "windsurf.jpg",
"size": 400,
"type": "file",
"extension": ".jpg"
}
]
}
]
},
{
"path": "photos/winter",
"name": "winter",
"size": 200,
"type": "directory",
"children": [
{
"path": "photos/winter/january",
"name": "january",
"size": 200,
"type": "directory",
"children": [
{
"path": "photos/winter/january/ski.png",
"name": "ski.png",
"size": 100,
"type": "file",
"extension": ".png"
},
{
"path": "photos/winter/january/snowboard.jpg",
"name": "snowboard.jpg",
"size": 100,
"type": "file",
"extension": ".jpg"
}
]
}
]
}
]
};
function tailRecurse(stack, result){
if (!stack.length)
return result;
// stack will contain
// the next object to examine
[obj, ref] = stack.pop();
if (obj.type == 'file'){
ref[obj.name] = obj.path;
} else if (obj.type == 'directory'){
ref[obj.name] = {};
for (let child of obj.children)
stack.push([child, ref[obj.name]]);
}
return tailRecurse(stack, result);
}
// Initialise
let _result = {};
let _stack = [[testObj, _result]];
console.log(tailRecurse(_stack, _result));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With