从包含文件路径的字符串列表创建树-javascript

时间:2019-08-04 07:28:05

标签: javascript path tree

假设我具有以下数组:

[
    "About.vue", 
    "Categories/Index.vue", 
    "Categories/Demo.vue", 
    "Categories/Flavors.vue"
]

我们在每个子文件夹中使用Index.vue充当该文件夹的父文件夹。那意味着上面看起来像:

[
  { 
    name: "About", 
    children: [] 
  }, 
  { 
    name: "Categories", 
    children: 
    [
      {
        name: "Index.vue", 
        children: [] 
      },
      {
        name: "Demo.vue", 
        children: [] 
      },
      { 
        name: "Flavors.vue", 
        children: [] 
      }
    ]
  }
]

通过使用以下教程,我可以使其稍作工作:https://joelgriffith.net/array-reduce-is-pretty-neat/

但是,与此有关的是,它是每个文件都具有属性的根对象,而不是每个文件都具有对象的数组。

以下代码产生预期的输出:

let paths = [
    "About.vue", 
    "Categories/Index.vue", 
    "Categories/Demo.vue", 
    "Categories/Flavors.vue"
];


let helper = {
  index: -1,
  name: ""
};

function treeify(files) {
  var fileTree = [];

  function mergePathsIntoFileTree(prevDir, currDir, i, filePath) {

    helper.name = currDir;
    helper.index = i;
      
    if (helper.index == 0) {
      let index = prevDir.findIndex(x => x.name == helper.name);
      if (index < 0) {
        prevDir.push({
          name: helper.name,
          children: []
        });
      }
      
      return prevDir;
    }
    
    if (helper.index >= 0) {
      let obj = {
        name: currDir,
        children: []
      };
      
      prevDir[helper.index].children.push(obj);
      helper.index = i;
      helper.name = currDir;
    }
   
  }

  function parseFilePath(filePath) {
    var fileLocation = filePath.split('/');

    // If file is in root directory, eg 'index.js'
    if (fileLocation.length === 1) {
      fileTree[0] = {
        name: fileLocation[0],
        children: []
      };
    } else {
      fileLocation.reduce(mergePathsIntoFileTree, fileTree);
    }
  }

  files.forEach(parseFilePath);

  return fileTree;
}

console.log(treeify(paths));

但是,它在以下输入中失败:

let paths = [
    "About.vue", 
    "Categories/Index.vue", 
    "Categories/Demo.vue", 
    "Categories/Flavors.vue",
    "Categories/Types/Index.vue",
    "Categories/Types/Other.vue"
];

有人知道一种使它适用于进一步嵌套的路径列表的解决方案吗?

3 个答案:

答案 0 :(得分:3)

您可以使用forEach方法创建此结构,以循环每个路径并将其拆分为/上的数组,然后还可以使用reduce方法来创建嵌套对象。

let paths = ["About.vue","Categories/Index.vue","Categories/Demo.vue","Categories/Flavors.vue","Categories/Types/Index.vue","Categories/Types/Other.vue"];

let result = [];
let level = {result};

paths.forEach(path => {
  path.split('/').reduce((r, name, i, a) => {
    if(!r[name]) {
      r[name] = {result: []};
      r.result.push({name, children: r[name].result})
    }
    
    return r[name];
  }, level)
})

console.log(result)

答案 1 :(得分:0)

您可以对找到的每个名称部分采用迭代方法,并获取一个对象,然后将其返回以进行下一次搜索。

var paths = ["About.vue", "Categories/Index.vue", "Categories/Demo.vue", "Categories/Flavors.vue", "Categories/Types/Index.vue", "Categories/Types/Other.vue"],
    result = paths.reduce((r, p) => {
        var names = p.split('/');
        names.reduce((q, name) => {
            var temp = q.find(o => o.name === name);
            if (!temp) q.push(temp = { name, children: [] });
            return temp.children;
        }, r);
        return r;
    }, []);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

答案 2 :(得分:0)

因此,首先,我要假设这是在Node.js中,其次,我目前在家里,所以我目前无法访问node.js,所以我没有真正的方法来测试代码,但是以下代码应该可以工作。

您需要做的是检查文件夹的内容,然后检查文件夹中的项目是否为目录,如果为true,则使用新路径(又称为递归)再次调用该函数。

因此,首先从阅读文件夹开始,将每个项目的名称添加到对象的 case "LIKED_POST": const { postDetails } = state; const newPostDetails = { ...postDetails, liked: true, likes: postDetails.likes + 1, }; return { ...state, postDetails: newPostDetails }; 属性中,然后检查该文件夹是否为该路径的递归文件夹。继续返回对象数组(这将添加到.name属性中。

.children

如果您不是使用node.js而是浏览器中的javascript,那么我无能为力