在JavaScript中将文件路径数组拆分为分层对象

Joh*_*ton 3 javascript jszip

使用JSZip可以在解压缩文件时为我提供文件夹和文件列表。例如当我跑步

files.forEach((relativePath, file) => {
  console.log(relativePath);
});
Run Code Online (Sandbox Code Playgroud)

我得到:

three-dxf-master/
three-dxf-master/.DS_Store
three-dxf-master/.gitignore
three-dxf-master/LICENSE
three-dxf-master/README.md
three-dxf-master/bower.json
three-dxf-master/bower_components/
Run Code Online (Sandbox Code Playgroud)

这些项目中有些是目录,有些是文件。我可以通过检查确定哪些是目录file.dir。我想将其拆分为分层数据结构。我想像这样拆分它:

{
  "three-dxf-master": [
    ".DS_Store",
    ".gitignore",
    "LICENSE",
    "README.md",
    "bower.json",
    {
      "bower_components": [
        ".DS_Store",
        {
          "dxf-parser": [...]
        }
      ]
    }
  ]
}
Run Code Online (Sandbox Code Playgroud)

这样,我可以将其发送到Vue并在一个不错的文件查看器中对其进行格式化。我浏览了文档,但没有找到一种简单的方法来为文件创建分层数据结构。我开始通过拆分后在文件路径中获取最后一个来调查此问题。

Ste*_*aud 5

这是一个示例代码,该代码也可以在根目录下处理文件。

请参阅以下代码段中的代码说明

var paths = [
    "three-dxf-master/",
    "three-dxf-master/.DS_Store",
    "three-dxf-master/.gitignore",
    "three-dxf-master/LICENSE",
    "three-dxf-master/README.md",
    "three-dxf-master/bower.json",
    "three-dxf-master/bower_components/",
    "three-dxf-master/bower_components/.DS_Store",
    "three-dxf-master/bower_components/dxf-parser/",
    "three-dxf-master/bower_components/dxf-parser/foo",
    "three-dxf-master/bower_components/dxf-parser/bar",
    "three-dxf-master/dummy_folder/",
    "three-dxf-master/dummy_folder/foo",
    "three-dxf-master/dummy_folder/hello/",
    "three-dxf-master/dummy_folder/hello/hello",
]

// Extract a filename from a path
function getFilename(path) {
    return path.split("/").filter(function(value) {
        return value && value.length;
    }).reverse()[0];
}

// Find sub paths
function findSubPaths(path) {
    // slashes need to be escaped when part of a regexp
    var rePath = path.replace("/", "\\/");
    var re = new RegExp("^" + rePath + "[^\\/]*\\/?$");
    return paths.filter(function(i) {
        return i !== path && re.test(i);
    });
}

// Build tree recursively
function buildTree(path) {
    path = path || "";
    var nodeList = [];
    findSubPaths(path).forEach(function(subPath) {
        var nodeName = getFilename(subPath);
        if (/\/$/.test(subPath)) {
            var node = {};
            node[nodeName] = buildTree(subPath);
            nodeList.push(node);
        } else {
            nodeList.push(nodeName);
        }
    });
    return nodeList;
}

// Build tree from root
var tree = buildTree();

// By default, tree is an array
// If it contains only one element which is an object, 
// return this object instead to match OP request
if (tree.length == 1 && (typeof tree[0] === 'object')) {
    tree = tree[0];
}

// Serialize tree for debug purposes
console.log(JSON.stringify(tree, null, 2));
Run Code Online (Sandbox Code Playgroud)

说明

function getFilename(path) {
    return path.split("/").filter(function(value) {
        return value && value.length;
    } ).reverse()
    [0];
}
Run Code Online (Sandbox Code Playgroud)

要获取文件名,请使用路径分隔路径/

/ path / to / dir / => ['path', 'to', 'dir', '']

/ path / to / file => ['path', 'to', 'file']

仅保留具有长度的值,此句柄目录路径。

文件名是数组的最后一个值,要获取它,我们可以简单地反转数组并获取第一个元素。

function findSubPaths(path) {
    // slashes need to be escaped when part of a regexp
    var rePath = path.replace("/", "\\/");
    var re = new RegExp("^" + rePath + "[^\\/]*\\/?$");
    return paths.filter(function(i) {
        return i !== path && re.test(i);
    });
}
Run Code Online (Sandbox Code Playgroud)

要查找路径的子路径,我们在路径列表上使用过滤器。

过滤器使用正则表达式(此处提供演示)来测试路径是从父路径开始还是以/(这是目录路径)或行的结尾(这是文件路径)结尾。

如果测试的路径不等于父路径并且匹配正则表达式,则过滤器会接受它。否则将被拒绝。

function buildTree(path) {
    path = path || "";
    var nodeList = [];
    findSubPaths(path).forEach(function(subPath) {
        var nodeName = getFilename(subPath);
        if(/\/$/.test(subPath)) {
            var node = {};
            node[nodeName] = buildTree(subPath);
            nodeList.push(node);            
        }
        else {
            nodeList.push(nodeName);
        }   
    });
    return nodeList;
}
Run Code Online (Sandbox Code Playgroud)

现在我们有了从路径中提取文件名并找到子路径的方法,很容易构建我们的树。树是一个nodeList。

如果子路径以结尾,/则为dir,buildTree然后在将节点附加到nodeList之前递归调用。

否则,我们只需将文件名添加到nodeList。

附加代码

if (tree.length == 1 && (typeof tree[0] === 'object')) {
    tree = tree[0];
}
Run Code Online (Sandbox Code Playgroud)

默认情况下,返回的树是一个数组。

为了匹配OP request,如果它只包含一个对象,那么我们返回该对象。