前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >js 实现扁平数组转为树形结构数组及树形结构数组转为扁平数组

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

作者头像
蓓蕾心晴
发布2022-09-24 14:55:09
1.8K0
发布2022-09-24 14:55:09
举报
文章被收录于专栏:前端小叙前端小叙
代码语言:javascript
复制
// 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);

注意:

  1. 扁平数组转为属性结构数组,如果使用递归实现,时间复杂度为 O(2^n)
  2. 注意修改原数组是否有影响,如果有影响,并且有原数组引用会产生问题。

转载请注明出处:https://cloud.tencent.com/developer/article/2121030

参考链接:

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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-09-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档