使用路径从dropbox api delta创建目录树

时间:2017-10-26 14:15:09

标签: javascript angularjs arrays

我发现了如何将文件路径转换为treeview的问题?但我不确定如何在JavaScript中获得所需的结果:

我正在尝试将一组路径转换为JSON树:

 var paths = [
        "/org/openbmc/UserManager/Group",
        "/org/stackExchange/StackOverflow",
        "/org/stackExchange/StackOverflow/Meta",
        "/org/stackExchange/Programmers",
        "/org/stackExchange/Philosophy",
        "/org/stackExchange/Religion/Christianity",
        "/org/openbmc/records/events",
        "/org/stackExchange/Religion/Hinduism",
        "/org/openbmc/HostServices",
        "/org/openbmc/UserManager/Users",
        "/org/openbmc/records/transactions",
        "/org/stackExchange/Religion/Islam",
        "/org/openbmc/UserManager/Groups",
        "/org/openbmc/NetworkManager/Interface"
    ];

我想使用文件夹路径获得如下所示的json结构。

        var xyz = [{
            "path": "photos",
            "name": "photos",
            "children": [
              {
                "path": "photos/summer",
                "name": "summer",
                "children": [
                  {
                    "path": "photos/summer/june",
                    "name": "june",
                    "children": [
                      {
                        "path": "photos/summer/june/windsurf",
                        "name": "windsurf",
                      }
                    ]
                  }
                ]
              },
              {
                "path": "photos/winter",
                "name": "winter",
                "children": [
                  {
                    "path": "photos/winter/january",
                    "name": "january",
                    "children": [
                      {
                        "path": "photos/winter/january/ski",
                        "name": "ski",
                      },
                      {
                        "path": "photos/winter/january/snowboard",
                        "name": "snowboard",
                      }
                    ]
                  }
                ]
              }
            ]
    }];

我使用了以下功能,但它无效

var parsePathArray = function(paths) {
var parsed = [];
for (var i = 0; i < paths.length; i++) {
    var position = parsed;
    var split = paths[i].split('/');
    for (var j = 0; j < split.length; j++) {
        if (split[j] !== "") {
            if (typeof position[split[j]] === 'undefined')
                position[split[j]] = {};
            position.children = [position[split[j]]];
            position.name = split[j];
            position = position[split[j]];

        }
    }
}
return parsed;
}

1 个答案:

答案 0 :(得分:0)

免责声明:我写这个答案是因为这是一个有趣的练习。我仍然对你没有尝试而没有花时间解释你不明白的感到失望......

我没有遵循您的确切格式,因此您必须尝试了解它是如何完成的,而不是能够复制代码并离开:)

我会简单地谈谈每一步,不要冒险解释你已经知道的事情。

第1步:

从字符串列表转到数组列表:

["a/1", "a/2", "b/1"] -> [["a", "1"], ["a", "2"], ["b", "1"]]

我们使用String.prototype.slice删除前缀“/”和String.prototype.split并使用您的文件夹分隔符转换为数组:path.split("/")

第2步

遍历每个文件夹并将文件夹添加到对象。

[["a", "1"], ["a", "2"], ["b", "1"]] -> { a: { 1: {}, 2: {} }, b: { 1: {} } }

我们使用一个使用括号表示法obj[key]访问对象的reducer,实例化新的文件夹对象并返回沿途最深的位置。

第3步

递归循环遍历对象的键并转换为指定的格式:

{ a: { 1: { } } -> { name: "a", path: [], children: [ /* ... */ ] }

我们使用Object.keys获取一个键列表,即文件夹名称。递归调用每个嵌套对象。

请使用特定步骤更新您的答案,以便其他人也可以提供帮助,我可以更详细地描述该步骤。

const pathStrings = ["/org/openbmc/UserManager/Group", "/org/stackExchange/StackOverflow", "/org/stackExchange/StackOverflow/Meta", "/org/stackExchange/Programmers", "/org/stackExchange/Philosophy", "/org/stackExchange/Religion/Christianity", "/org/openbmc/records/events", "/org/stackExchange/Religion/Hinduism", "/org/openbmc/HostServices", "/org/openbmc/UserManager/Users", "/org/openbmc/records/transactions", "/org/stackExchange/Religion/Islam", "/org/openbmc/UserManager/Groups", "/org/openbmc/NetworkManager/Interface"];

const paths = pathStrings
    .map(str => str.slice(1))       // remove first "/"
    .map(str => str.split("/"));

// Mutates map!
const mergePathInToMap = (map, path) => {
    path.reduce(
        (loc, folder) => (loc[folder] = loc[folder] || {}, loc[folder]),
        map      
    );

    return map;
};

// Folder structure as { folderName: folderContents }
const folderMap = paths.reduce(mergePathInToMap, {});

// Go from 
//   { folderName: folderContents }
// to a desired format like 
//   { name: folderName, children: [contents] }
const formatStructure = (folder, path) => {
    return Object
        .keys(folder)
        .map(k => ({ 
            name: k,
            path: path,
            children: formatStructure(folder[k], path.concat(k))
        }))
    
}

console.log(
    JSON.stringify(
        formatStructure(folderMap, []),
        null,
        2
    )
)
.as-console-wrapper { min-height: 100% }