从多个字符串路径创建嵌套对象

时间:2017-06-21 15:12:17

标签: javascript

我正在寻找使用javascript将多个字符串路径转换为嵌套对象的最佳方法。我正在使用lodash,如果这可能有任何帮助。

我有以下路径:

/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

我想创建以下对象数组:

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

2 个答案:

答案 0 :(得分:7)

我建议实现一个树插入函数,其参数是一个子数组和一个路径。它根据给定的路径遍历子节点并根据需要插入新的子节点,避免重复:

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

答案 1 :(得分:1)

迭代每个字符串并将其解析为对象:

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

改进版本:

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

它创建相同的结果,但它可能更快(最多O(n)对O(n + n!)) http://jsbin.com/xumazinesa/edit?console