Creating a nested object from multiple lines

I am looking for a better way to convert multiple string paths to a nested object using javascript. I use lodash if this can help anyway.

I got the following paths:

/root/library/Folder 1 /root/library/Folder 2 /root/library/Folder 1/Document.docx /root/library/Folder 1/Document 2.docx /root/library/Folder 2/Document 3.docx /root/library/Document 4.docx 

and I would like to create the following array of object:

  var objectArray = [ { "name": "root", "children": [ { "name": "library", "children": [ { "name": "Folder 1", "children": [ { "name": "Document.docx", "children": [] }, { "name": "Document 2.docx", "children": [] } ] }, { "name": "Folder 2", "children": [ { "name": "Document 3.docx", "children": [] } ] }, { "name": "Document 4.docx", "children": [] } ] } ] } ]; 
+5
source share
2 answers

I suggest implementing a tree insert function whose arguments are an array of children and a path. It moves children along a given path and inserts new children as necessary, avoiding duplicates:

 // Insert path into directory tree structure: function insert(children = [], [head, ...tail]) { let child = children.find(child => child.name === head); if (!child) children.push(child = {name: head, children: []}); if (tail.length > 0) insert(child.children, tail); return children; } // Example: let paths = [ '/root/library/Folder 1', '/root/library/Folder 2', '/root/library/Folder 1/Document.docx', '/root/library/Folder 1/Document 2.docx', '/root/library/Folder 2/Document 3.docx', '/root/library/Document 4.docx' ]; let objectArray = paths .map(path => path.split('/').slice(1)) .reduce((children, path) => insert(children, path), []); console.log(objectArray); 
+6
source

Loop over each line and allow it to object:

 var glob={name:undefined,children:[]}; ["/root/library/Folder 1","/root/library/Folder 2","/root/library/Folder 1/Document.docx","/root/library/Folder 1/Document 2.docx","/root/library/Folder 2/Document 3.docx","/root/library/Document 4.docx"] .forEach(function(path){ path.split("/").slice(1).reduce(function(dir,sub){ var children; if(children=dir.children.find(el=>el.name===sub)){ return children; } children={name:sub,children:[]}; dir.children.push(children); return children; },glob); }); console.log(glob); 

http://jsbin.com/yusopiguci/edit?console


Enhanced Version:

 var glob={name:undefined,children:[]}; var symbol="/" /* or Symbol("lookup") in modern browsers */ ; var lookup={[symbol]:glob}; ["/root/library/Folder 1","/root/library/Folder 2","/root/library/Folder 1/Document.docx","/root/library/Folder 1/Document 2.docx","/root/library/Folder 2/Document 3.docx","/root/library/Document 4.docx"] .forEach(function(path){ path.split("/").slice(1).reduce(function(dir,sub){ if(!dir[sub]){ let subObj={name:sub,children:[]}; dir[symbol].children.push(subObj); return dir[sub]={[symbol]:subObj}; } return dir[sub]; },lookup); }); console.log(glob); 

It produces the same result, but can be much faster (to O (n) vs O (n + n!)) Http://jsbin.com/xumazinesa/edit?console

+1
source

Source: https://habr.com/ru/post/1269069/


All Articles