Javascript 多维数组到单个对象

Javascript multidimentional array to single object

我很难写一个算法。上下文如下:我有一组路径,我想将它们放入单个对象中,例如重建文件树。

这是一个简单的示例:

var paths = [  
  '/var/log/log.txt',  
  '/var/log/test.txt',  
  '/home/toto/someFile.txt',
  '/wtf.txt'  
];

我希望这个路径数组是一个对象,例如:

var tree = {  
  var: {
    log: ['log.txt', 'test.txt']
  },
  home: {
    toto: ['someFile.txt']
  },
  wtf.txt: null // I don't know how to handle this case
};

关于如何做这样的事情有什么提示吗?

实际上,我有类似的东西,但它以单一深度级别结束,而不是在根级别处理文件:

function rebuildTree(paths, tree) {
  paths.forEach(function (path) {
      var splittedPath;
      if (path.indexOf("/") > -1) {
          splittedPath = path.split('/');
      } else {
          splittedPath = [path];
      }

      splittedPath.some(function(item, index) {
          if (!tree.hasOwnProperty(item) && index > 0) {
              tree[item] = {};
          }

          if ((parseInt(index) + 1) <= (splittedPath.length - 1)) {
              var nextIndex = parseInt(index + 1);
              var nextPath = splittedPath.splice(0, index);
              tree[item] = rebuildTree(nextPath, tree[item]);
          }
      });
  });
} 

我在下面写了一个小辅助函数,应该很容易做到,请查看评论以了解它是如何工作的(请查看您的控制台以获取输出)。

function treeify(paths){

  // This will store our tree
  var tree = {};
  
  // This will run through all our paths
  paths.forEach(function(path){
    
    // This will remove the initial slash
    if(path.indexOf('/') === 0) path = path.substring(1);
    
    // Find all the individual files/folders
    path = path.split('/');
    
    // If there is only one we'll assume its a file and assign your `null`
    if(path.length === 1){
       tree[path[0]] = tree[path[0]] || null;
       return;
    }
    
    // Create a variable that will store the current branch we are in
    var branch = tree[path[0]] = tree[path[0]] || {};
    
    // Loop through the remaining values, repointing the branch as we go.
    for(var i = 1; i < path.length; i++){
      // The second to last item will need to be an array (as suggested).
      if(i === path.length-2)
        branch = branch[path[i]] = branch[path[i]] || [];
      // The last item will be pushed to the array (as suggested).
      else if(i === path.length-1)
        branch.push(path[i]);
      // All others will simply create a new branch.
      else
        branch = branch[path[i]] = branch[path[i]] || {};
    }
    
  });
  
  return tree;
}

console.log(treeify([  
  '/var/log/log.txt',  
  '/var/log/test.txt',  
  '/home/toto/someFile.txt',
  '/wtf.txt'  
]));

最大的缺点是它会因为你想要的结构而崩溃。更好的解决方案如下所示,它降低了复杂性并使其更易于理解:

function treeify(paths){

  var tree = {};
  
  paths.forEach(function(path){
    
    if(path.indexOf('/') === 0) path = path.substring(1);
    path = path.split('/');
    
    var branch = tree[path[0]] = tree[path[0]] || {};
    
    for(var i = 1; i < path.length; i++){
        branch = branch[path[i]] = branch[path[i]] || {};
    }
    
  });
  
  return tree;
}

console.log(treeify([  
  '/var/log/log.txt',  
  '/var/log/test.txt',  
  '/home/toto/someFile.txt',
  '/wtf.txt'  
]));

在此代码段中,所有路径都只是嵌套键,您可以使用 for..in 结构来查找内容。它不太方便,但以数组结尾可能会导致以下问题:当您有两条路径时,一条是 a/b/c.txt,另一条是 a/b/c/d,推送将中断并且数组将失败。这意味着你只能有一个深度级别,而这个函数可以有任何级别的深度。