2017-06-21 29 views
5

Tôi đang tìm cách tốt nhất để chuyển đổi nhiều đường dẫn chuỗi thành đối tượng lồng nhau bằng javascript. Tôi đang sử dụng lodash nếu điều đó có thể giúp bằng bất kỳ cách nào.Tạo đối tượng lồng nhau từ nhiều đường dẫn chuỗi

tôi có các đường dẫn sau:

/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 

và tôi muốn tạo ra các mảng sau đây của đối tượng:

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": [] 
       } 
      ] 
      } 
     ] 
     } 
    ]; 

Trả lời

6

Tôi đề nghị thực hiện một chức năng chèn cây có đối số là một mảng của trẻ em và một con đường. Nó đi qua những đứa trẻ theo con đường nhất định và chèn trẻ em mới khi cần thiết, tránh lặp:

// 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);

+0

tôi tự hỏi câu trả lời nào nhanh hơn, này hoặc @Jonasw. bất cứ suy nghĩ nào? Điều này đối với tôi là dễ đọc hơn nhiều. woudl lên hai lần nếu posible. : D –

+0

@GeomanYabes này bằng câu trả lời đầu tiên của tôi (tuy nhiên nó trông đẹp hơn nhiều) –

+0

@GeomanYabes Hàm đệ quy này chặt chẽ theo cấu trúc cây kết quả và tìm kiếm trẻ phù hợp trong một mảng trong thời gian tuyến tính. Điều này có thể được cải thiện bằng cách ánh xạ trực tiếp các tên con đến các thuộc tính đối tượng của nút gốc cây và chuyển đổi sang bố cục mảng của OP sau này. Mà sẽ đến với một chi phí liên tục bổ sung, vì vậy có lẽ không mong muốn trừ khi OP đề với rất nhiều đường dẫn. –

1

lặp qua mỗi chuỗi và giải quyết nó đến một đối tượng:

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


Phiên bản cải tiến:

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); 

Nó tạo ra kết quả tương tự nhưng nó là có thể nhanh hơn nhiều (lên đến O (n) so với O (n + n)!) http://jsbin.com/xumazinesa/edit?console

+0

'dir.children [sub] 'sẽ không trở lại bất cứ điều gì. Nó sẽ tìm kiếm 'dir.children [" Folder 1 "]', vv 'dir.children' là một mảng các đối tượng, không phải là một đối tượng. Bạn sẽ thêm các thuộc tính vào đối tượng mảng, đó là một anti-pattern nếu tôi đã từng thấy nó. Đầu ra của bạn sẽ không giống như đầu ra mong muốn của OP – mhodges

+1

Dường như nó hoạt động ngay bây giờ. Nếu nó có một số khoảng trống, tôi sẽ upvote nó. –

+0

Có bạn đi, bây giờ có vẻ đúng. Không phải là người hâm mộ các bài tập trong các biểu thức có điều kiện, nhưng nó hoạt động. – mhodges

Các vấn đề liên quan