I have an array of objects that looks like this:
[{ name: 'test',
size: 0,
type: 'directory',
path: '/storage/test' },
{ name: 'asdf',
size: 170,
type: 'directory',
path: '/storage/test/asdf' },
{ name: '2.txt',
size: 0,
type: 'file',
path: '/storage/test/asdf/2.txt' }]
There could be any number of arbitrary path's, this is the result of iterating through files and folders within a directory.
What I'm trying to do is determine the 'root' node of these. Ultimately, this will be stored in mongodb and use materialized path to determine it's relationships.
In this example, /storage/test
is a root with no parent. /storage/test/asdf
has the parent of /storage/test
which is the parent to /storage/test/asdf/2.txt
.
My question is, how would you go about iterating through this array, to determine the parent's and associated children? Any help in the right direction would be great!
Thank you
Structure. The directory is structured in the form of a tree. It also has a root directory, and every file in the system has a unique path. A directory within a tree-structured directory may contain files or subdirectories.
You need to use command called tree. It will list contents of directories in a tree-like format. It is a recursive directory listing program that produces a depth indented listing of files. When directory arguments are given, tree lists all the files and/or directories found in the given directories each in turn.
A directory structure/system/tree is simply a layout of directories on your computer. Taking a big step back, the early computer designers realized that lumping together every single file on your computer would create a massive jumble and make it impossible to find anything. So they wisely created the directory.
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.
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