从包含文件路径的字符串列表创建一棵树 - javascript [英] Create a tree from a list of strings containing paths of files - javascript

查看:50
本文介绍了从包含文件路径的字符串列表创建一棵树 - javascript的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有以下数组:

<预><代码>["关于.vue","类别/索引.vue","类别/Demo.vue",类别/风味.vue"]

我们使用每个子文件夹中的 Index.vue 作为该文件夹的父文件夹.这意味着上面看起来像:

<预><代码>[{name: "关于",孩子们: []},{name: "类别",孩子们:[{name: "Index.vue",孩子们: []},{name: "Demo.vue",孩子们: []},{name: "Flavors.vue",孩子们: []}]}]

通过使用以下教程,我能够让它稍微工作起来:https://joelgriffith.net/array-reduce-is-pretty-neat/

然而,它是一个根对象,每个文件都有一个属性,而不是一个数组,每个文件都有一个对象.

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

let paths = ["关于.vue","类别/索引.vue","类别/Demo.vue",类别/风味.vue"];让帮手 = {指数:-1,名称: ""};功能树化(文件){var fileTree = [];函数 mergePathsIntoFileTree(prevDir, currDir, i, filePath) {helper.name = currDir;helper.index = i;如果(helper.index == 0){让 index = prevDir.findIndex(x => x.name == helper.name);如果(索引<0){prevDir.push({名称:helper.name,孩子们: []});}返回上一个目录;}如果 (helper.index >= 0) {让 obj = {名称:currDir,孩子们: []};prevDir[helper.index].children.push(obj);helper.index = i;helper.name = currDir;}}函数解析文件路径(文件路径){var fileLocation = filePath.split('/');//如果文件在根目录,例如'index.js'if (fileLocation.length === 1) {文件树[0] = {名称:文件位置[0],孩子们: []};} 别的 {fileLocation.reduce(mergePathsIntoFileTree, fileTree);}}files.forEach(parseFilePath);返回文件树;}console.log(treeify(paths));

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

let 路径 = ["关于.vue","类别/索引.vue","类别/Demo.vue","类别/风味.vue","类别/类型/Index.vue",类别/类型/其他.vue"];

有没有人知道一个解决方案,让它适用于进一步嵌套的路径列表?

解决方案

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

let paths = ["About.vue","Categories/Index.vue","Categories/Demo.vue","Categories/Flavors.vue","Categories/Types/Index.vue","Categories/Types/Other.vue"];让结果 = [];让级别 = {结果};路径.forEach(路径=> {path.split('/').reduce((r, name, i, a) => {如果(!r[名称]){r[名称] = {结果:[]};r.result.push({name, children: r[name].result})}返回 r[名称];}, 等级)})console.log(result)

Let's assume I have the following array:

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

We use the Index.vue in each sub-folder to act as the parent of that folder. That means the above would look like:

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

I was able to get it working slightly by using the following tutorial: https://joelgriffith.net/array-reduce-is-pretty-neat/

However, the thing about that is that it is a root object with a property for each file, as opposed to an array with an object for each file.

The following code produces the intended output:

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

However, it fails on the following input:

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

Does anyone know a solution to get it working for further nested lists of paths?

解决方案

You can create this structure using forEach method to loop each path and split it to array on /, then you can also use reduce method to create nested objects.

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)

这篇关于从包含文件路径的字符串列表创建一棵树 - javascript的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆