C V大法:JS 平面数组转换为tree形数组

692 阅读2分钟

CV.jpg

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

C V 系列特点:

  1. 只关注功能的实现。让各位看官复制粘贴即可安心使用
  2. 代码注释会写详细,尽可能做到一行一注释,把细节都说清楚
  3. 涉及第三方库等等不做赘述,用到的库会给各位看官放上的链接的,方便各位深入了解

话不多说 上代码

演示数据

const list = [
            { id: '1', path: "/views/dashBoard/index.vue", name: "一级", pid: "0" },
            { id: '2', path: "/views/dashBoard/index.vue", name: "二级", pid: "1" },
            { id: '3', path: "/views/dashBoard/index.vue", name: "二级", pid: "1" },
            { id: '4', path: "/views/dashBoard/index.vue", name: "三级", pid: "2" },
            { id: '5', path: "/views/dashBoard/index.vue", name: "三级", pid: "3" },
            { id: '6', path: "/views/dashBoard/index.vue", name: "四级", pid: "5" },
            { id: '7', path: "/views/dashBoard/index.vue", name: "一级", pid: "0" }]

方法一:(推荐)

执行效率:0.05712890625 ms 0.057左右

// 平面数组转换为树数组
const formatTree1 = (arr) => {
    let r = [];
    
    arr.forEach(function (a) {
        this[a.id] = a
        if (a.pid === '0') {
            r.push(this[a.id]);
        } else {
            this[a.pid] = this[a.pid] || {};
            this[a.pid].children = this[a.pid].children || [];
            this[a.pid].children.push(this[a.id]);
        }
    }, Object.create(null)); // Object.create(null) 必须写 用作 this 的值
    
    // 最终的数据
    return r;
}

console.time()
formatTree1(list)
console.timeEnd()

方法二:(推荐)

执行效率:0.064208984375 ms 0.06左右

// 平面数组转换为树数组
const formatTree2 = (arr) => {
    let kData = {} // 以id做key的对象 暂时储存数据
    let lData = [] // 最终的数据 arr

    arr.forEach(m => {
        kData[m.id] = m
        if (m.pid === '0') {
            lData.push(kData[m.id])
        } else {
            kData[m.pid] = kData[m.pid] || {}
            kData[m.pid].children = kData[m.pid].children || [];
            kData[m.pid].children.push(kData[m.id]);
        }
    })

    // 最终的数据
    return lData
}

console.time()
formatTree2(list)
console.timeEnd()

方法三:(不推荐)

执行效率: 0.115966796875 ms 0.11左右

// 平面数组转换为树数组
const formatTree3 = (arr) => {
    let parents = arr.filter(item => String(item.pid) === '0'); //取出根节点
    let childrens = arr.filter(item => String(item.pid) !== '0');//去除子节点

    function translator(parents, childrens) {
        parents.forEach(item => {
            childrens.forEach(items => {
                if (String(items.pid) === String(item.id)) {
                    item.children ? item.children.push(items) : item.children = [items];
                    translator([items], childrens);
                }
            })
        })
    }

    translator(parents, childrens);

    // 最终的数据
    return parents
}

console.time()
formatTree3(list)
console.timeEnd()

最终的输出结构

[
    {
        "id": "1",
        "path": "/views/dashBoard/index.vue",
        "name": "一级",
        "pid": "0",
        "children": [
            {
                "id": "2",
                "path": "/views/dashBoard/index.vue",
                "name": "二级",
                "pid": "1",
                "children": [
                    {
                        "id": "4",
                        "path": "/views/dashBoard/index.vue",
                        "name": "三级",
                        "pid": "2"
                    }
                ]
            },
            {
                "id": "3",
                "path": "/views/dashBoard/index.vue",
                "name": "二级",
                "pid": "1",
                "children": [
                    {
                        "id": "5",
                        "path": "/views/dashBoard/index.vue",
                        "name": "三级",
                        "pid": "3",
                        "children": [
                            {
                                "id": "6",
                                "path": "/views/dashBoard/index.vue",
                                "name": "四级",
                                "pid": "5"
                            }
                        ]
                    }
                ]
            }
        ]
    },
    {
        "id": "7",
        "path": "/views/dashBoard/index.vue",
        "name": "一级",
        "pid": "0"
    }
]

补充

测试出来的效率不是很稳定,我上面给出的是我测试中经常出现的一个数值

欢迎查看更多C V系列 C V 大法