transform file/directory structure into 'tree' in javascript
You can do it like this:
var arr = [] //your array;
var tree = {};
function addnode(obj){
var splitpath = obj.path.replace(/^\/|\/$/g, "").split('/');
var ptr = tree;
for (i=0;i<splitpath.length;i++)
{
node = { name: splitpath[i],
type: 'directory'};
if(i == splitpath.length-1)
{node.size = obj.size;node.type = obj.type;}
ptr[splitpath[i]] = ptr[splitpath[i]]||node;
ptr[splitpath[i]].children=ptr[splitpath[i]].children||{};
ptr=ptr[splitpath[i]].children;
}
}
arr.map(addnode);
console.log(require('util').inspect(tree, {depth:null}));
Output
{ storage:
{ name: 'storage',
type: 'directory',
children:
{ test:
{ name: 'test',
type: 'directory',
size: 0,
children:
{ asdf:
{ name: 'asdf',
type: 'directory',
size: 170,
children: { '2.txt': { name: '2.txt', type: 'file', size: 0, children: {} } } } } } } } }
Assuming /
will never show up in the list of files, something like this should work:
function treeify(files) {
var path = require('path')
files = files.reduce(function(tree, f) {
var dir = path.dirname(f.path)
if (tree[dir]) {
tree[dir].children.push(f)
} else {
tree[dir] = { implied: true, children: [f] }
}
if (tree[f.path]) {
f.children = tree[f.path].children
} else {
f.children = []
}
return (tree[f.path] = f), tree
}, {})
return Object.keys(files).reduce(function(tree, f) {
if (files[f].implied) {
return tree.concat(files[f].children)
}
return tree
}, [])
}
It'll turn the array you mention in the question in to something like this:
[ { name: 'test',
size: 0,
type: 'directory',
path: '/storage/test',
children:
[ { name: 'asdf',
size: 170,
type: 'directory',
path: '/storage/test/asdf',
children:
[ { name: '2.txt',
size: 0,
type: 'file',
path: '/storage/test/asdf/2.txt',
children: [] } ] } ] } ]
I haven't actually tested this with any other data sources, so your milage may vary but at least it ought to nudge you in the right direction.