Skip to content

📚 11.文件路径转换

💻 代码实现

typescript
const baseData = ['a/b/c/d/e', 'a/b/e/f/g', 'a/b/h', 'a/i/j', 'a/i/k'];
// 转换成 ==========================>

// {
//   "key": "a",
//   "children": [
//     {
//       "key": "b",
//       "children": [
//         {
//           "key": "c",
//           "children": [
//             {
//               "key": "d",
//               "children": [
//                 { "key": "e" }
//               ]
//             }
//           ]
//         },
//         {
//           "key": "e",
//           "children": [
//             {
//               "key": "f",
//               "children": [
//                 { "key": "g" }
//               ]
//             }
//           ]
//         },
//         { "key": "h" }
//       ]
//     },
//     {
//       "key": "i",
//       "children": [
//         { "key": "j" },
//         { "key": "k" }
//       ]
//     }
//   ]
// }
function pathToTree(arr) {
    const res = [] // 存储结果
    // 每一次循环处理一个节点,如果有的话就跳过,如果没有的话,则push到children
    arr.forEach(item => {
        const nodeTokens = item.split('/')
        let targetPoint = res // 目标节点, 始终是数组

        for (let node of nodeTokens) {
            const nodeObj = {
                key: node,
                children: []
            }
            /** 是否存在 */
            let isExit = false
            for (let j of targetPoint) {
                if (j.key === node) {
                    if (!j.children) {
                        j.children = []
                    }
                    targetPoint = j.children
                    isExit = true
                    break
                }
            }

            if (!isExit) {
                targetPoint.push(nodeObj)
                // ps: targetPoint然后操控当前节点的children
                if (!targetPoint[targetPoint.length - 1].children) {
                    targetPoint[targetPoint.length - 1].children = []
                }
                targetPoint = targetPoint[targetPoint.length - 1].children
            }
        }
    })
    return res
}

pathToTree(baseData)

// 递归的做法
function pathToTree(paths) {
    const tree = [];

    // ps: node是每一层的children  parts是当前的一个路径 index是当前路径的一个索引
    const addNode = (node, parts, index) => {
        // 终止条件:处理完所有路径片段 
        if (index === parts.length) return;

        const current = parts[index];
        // 查找是否已存在同名节点 
        let child = node.find(item => item.name === current);

        // 创建新节点(区分文件与文件夹)
        if (!child) {
            child = {
                name: current,
                children: index === parts.length - 1 ? null : [] // 文件节点无children 
            };
            node.push(child);
        }

        // 递归处理下一级路径(仅文件夹需要继续遍历)
        if (child.children) {
            addNode(child.children, parts, index + 1);
        }
    };

    paths.forEach(path => {
        const parts = path.split('/').filter(Boolean);  // 过滤空路径段
        addNode(tree, parts, 0);
    });
    return tree;
}

Released under the MIT License.