将多个文件路径处理成树形结构

97 阅读2分钟

树形结构数据的处理笔试时经常会出现,本文将以文件路径转化为树形结构为例:

一、需求与目标

1.1 待处理数据

const paths = [
    '/Users/77952/Desktop/grow/工作/钧仔简历/面试项目',
    '/Users/77952/Pictures/吞噬星空.jpg',
    '/Users/77952/Desktop/grow/医学文件'
];

1.2 目标

{
    "id": 1,
    "name": "Users",
    "parent_id": null,
    "children": [{
        "id": 2,
        "name": "77952",
        "parent_id": 1,
        "children": [{
                "id": 3,
                "name": "Desktop",
                "parent_id": 2,
                "children": [{
                    "id": 4,
                    "name": "grow",
                    "parent_id": 3,
                    "children": [{
                            "id": 5,
                            "name": "工作",
                            "parent_id": 4,
                            "children": [{
                                "id": 6,
                                "name": "钧仔简历",
                                "parent_id": 5,
                                "children": [{
                                    "id": 7,
                                    "name": "面试项目",
                                    "parent_id": 6,
                                    "children": []
                                }]
                            }]
                        },
                        {
                            "id": 10,
                            "name": "医学文件",
                            "parent_id": 4,
                            "children": []
                        }
                    ]
                }]
            },
            {
                "id": 8,
                "name": "Pictures",
                "parent_id": 2,
                "children": [{
                    "id": 9,
                    "name": "吞噬星空.jpg",
                    "parent_id": 8,
                    "children": []
                }]
            }
        ]
    }]
}

二、实现过程

2.1 第一步:初始化Map数据结构 + 唯一节点id

    //1.初始化数据结构 + 唯一节点id
    const nodesMap = new Map()
    let idCounter = 1 //唯一节点id

2.2 第二步:遍历 => 分割路径 + 过滤空串 + 创建节点 + 更新父节点id

paths.forEach(path => {
    const parts = path.split('/').filter(Boolean)
    let parent_id = null //最外层父节点

    parts.forEach(part => {
        const node = createNode(part, parent_id)
        parent_id = node.id // 更新父节点id
    })
})
console.log("%c nodesMap", "color:red;", nodesMap);
// 创建节点
function createNode(name, parent_id) {
    //文件夹名称可能会相同:检查节点是否已存在,如果存在,则返回该节点
    for (let [_, node] of nodesMap) {
        if (node.name === name && node.parent_id === parent_id) {
            return node
        }
    }

    //如果节点不存在,则创建新节点,并返回
    const newNode = {
        id: idCounter++,
        name,
        parent_id,
        children: []
    }

    nodesMap.set(newNode.id, newNode)
    return newNode
}

image.png

2.3 第三步:将节点转化为树形结构

    // 树形结构辅助根数据
    const result = {
        name: 'root',
        children: []
    }

    // 3.遍历 => 将节点转化为树形结构
    for (let [_, node] of nodesMap) {
        if (node.parent_id === null) {
            result.children.push(node)
        } else {
            const parent = nodesMap.get(node.parent_id)
            if (parent) {
                parent.children.push(node)
            }
        }
    }

第四步:返回树形结构数据

// 4.返回树形结构
return result.children[0]