js 实现扁平数组转为树形结构数组及树形结构数组转为扁平数组

// pid 代表属于的父级 id
// id 代表的是自己本身的id,本身的 id 是多少
let flatArr = [
    { id: 1, name: "部门1", pid: 0 },
    { id: 2, name: "部门2", pid: 1 },
    { id: 3, name: "部门3", pid: 1 },
    { id: 4, name: "部门4", pid: 3 },
    { id: 5, name: "部门5", pid: 4 },
];
// 预期输出
// [
//     {
//         id: 1,
//         name: "部门1",
//         pid: 0,
//         children: [
//             { id: 2, name: "部门2", pid: 1 },
//             {
//                 id: 3,
//                 name: "部门3",
//                 pid: 1,
//                 children: [
//                     {
//                         id: 4,
//                         name: "部门4",
//                         pid: 3,
//                         children: [{ id: 5, name: "部门5", pid: 4 }],
//                     },
//                 ],
//             },
//         ],
//     },
// ]
// 预期输出:
// 1. 子节点的pid是父节点的id,即某个对象的 pid 与 某个对象的 id 相同,则前者为后者的子节点
// 2. 返回为带有层级的对象数组
// 步骤
// 为了避免使用递归导致的性能较差,每次遍历一遍数字,这里使用 map 存储对象
// 1.先将每个对象变为通过 id 保存的具体对象的map 对象
// 2.创建结果数组
// 3.遍历传入的数组,根据传入的 parent_id(pid),获取所有父节点的对象,push 到数组中,作为第一层对象
// 4.在遍历数组过程中,获取数组的 pid,从刚才保存的对象中寻找父级对象是否存在如果存在,增加 children 属性,数组,并 push 当前对象
// arr 为传入的待转换的扁平数组
// parentId 为根节点 id
function arrayToTree(arr, parentId) {
    // 将所有对象存到 map 中
    const map = arr.reduce((prev, cur) => {
        // 注意:这里是浅拷贝,会修改原数组,当后续再使用原数组会出问题
        prev[cur.id] = cur;
        return prev;
    }, {});
    // 定义返回结果数组
    let result = [];
    // 遍历传入的对象
    for (let i = 0; i < arr.length; i++) {
        const item = arr[i];
        // 当遍历到的对象的 pid 等于 传入的根节点的 id,说明为根节点,直接 push 到数组中
        if (item.pid === parentId) {
            result.push(item);
            // 退出本次循环
            continue;
        }
        // 如果不是根节点,从 map 中找到 pid 对应的对象,该对象即为当前遍历到的对象的父节点
        const parent = map[item.pid];
        if (parent) {
            // 给父节点添加 children 属性,并定义为数组
            parent.children = parent.children || [];
            // 在数组中 push 当前子节点
            parent.children.push(item);
        }
    }
    return result;
}
console.log(arrayToTree(flatArr, 0));

// 不改变原数组的方法
function arrayToTree2(items) {
    const result = []; // 存放结果集
    const itemMap = {}; //
    for (const item of items) {
        const id = item.id;
        const pid = item.pid;

        if (!itemMap[id]) {
            itemMap[id] = {
                children: [],
            };
        }

        itemMap[id] = {
            ...item,
            children: itemMap[id]["children"],
        };

        const treeItem = itemMap[id];

        if (pid === 0) {
            result.push(treeItem);
        } else {
            if (!itemMap[pid]) {
                itemMap[pid] = {
                    children: [],
                };
            }
            itemMap[pid].children.push(treeItem);
        }
    }
    return result;
}
console.log(arrayToTree2(flatArr));
let treeArr = [
    {
        id: 1,
        name: "部门1",
        pid: 0,
        children: [
            { id: 2, name: "部门2", pid: 1 },
            {
                id: 3,
                name: "部门3",
                pid: 1,
                children: [
                    {
                        id: 4,
                        name: "部门4",
                        pid: 3,
                        children: [{ id: 5, name: "部门5", pid: 4 }],
                    },
                ],
            },
        ],
    },
];
// 树形结构转为扁平数组
function flatten(arr) {
    return arr.reduce((prev, cur) => {
        const { children = [], ...others } = cur;
        return prev.concat([{ ...others }], flatten(children));
    }, []);
}
console.log("树形数组转为扁平数组");
console.log(flatten(treeArr));
console.log(treeArr);
// 无 pid,需要手动加 pid
            let treeArr1 = [
                {
                    id: 1,
                    name: "部门1",
                    children: [
                        { id: 2, name: "部门2" },
                        {
                            id: 3,
                            name: "部门3",
                            children: [
                                {
                                    id: 4,
                                    name: "部门4",
                                    children: [{ id: 5, name: "部门5" }],
                                },
                            ],
                        },
                    ],
                },
            ];

function treeToFlat1(treeArr, pid) {
                return treeArr.reduce((prev, cur) => {
                    const { children = [], ...others } = cur;
                    return prev.concat({ pid, ...others }, treeToFlat1(children, cur.id));
                }, []);
            }

注意:

1. 扁平数组转为树形结构数组,如果使用递归实现,时间复杂度为 O(2^n)

2. 注意修改原数组是否有影响,如果有影响,并且有原数组引用会产生问题。

转载请注明出处:https://www.cnblogs.com/beileixinqing/p/16666662.html

参考链接:

https://www.bilibili.com/video/BV1mQ4y1X7S9?spm_id_from=333.337.search-card.all.click&vd_source=194f8fed26c3607cae375c20d6e308f0

https://juejin.cn/post/6983904373508145189#heading-8

https://blog.csdn.net/Zero_kuma/article/details/120798602

posted @ 2022-09-07 17:39  蓓蕾心晴  阅读(1198)  评论(0编辑  收藏  举报