JavaScript将扁平数组转化为父子树结构 递归 map映射

问题背景:在工作和学习过程中,可能会遇到需要将扁平数组转换成父子结构的情景,比如使用elementUI的  table 表格 或者 tree 树形控件的时候,需要组成父子结构的情景

        通常来说,后端返回的数据是一个扁平的数组结构,前端接收到数据后,根据数组项的parantId 和 id ,将数组重新构造成一个父子树结构,再赋值给组件,达到需要的效果。

构造前的扁平数组结构:

[
  { id: '1', parentId: '', name: 'Root' },
  { id: '2', parentId: '1', name: 'Child 1' },
  { id: '3', parentId: '1', name: 'Child 2' },
  { id: '4', parentId: '2', name: 'Grandchild 1' },
  { id: '5', parentId: '2', name: 'Grandchild 2' }
]

构造后的父子树结构:

// 构造后
[
  {
    id: '1',
    parentId: '',
    name: 'Root',
    children: [
      {
        id: '2',
        parentId: '1',
        name: 'Child 1',
        children: [
          { id: '4', parentId: '2', name: 'Grandchild 1' },
          { id: '5', parentId: '2', name: 'Grandchild 2' }
        ]
      },
      {
        id: '3',
        parentId: '1',
        name: 'Child 2'
      }
    ]
  }
]

方法一:forEach递归遍历构造树结构

    //根据parentId和 orgId构造树结构
    const buildTreeStructure = (array) => {
        // 构造父节点列表
        let parentList = array.filter(el => el.parentId== '' || el.parentId== null);
        // 构造存在父Id的子节点列表
        let sonList = array.filter(el => el.parentId!= '' && el.parentId!= null);

        dataToTree(parentList, sonList);

        // 将数据转换为树形结构
        function dataToTree(parents, child) {
            // 遍历父节点
            parents.forEach((p) => {
                // 遍历子节点
                child.forEach((c, i) => {
                    // 如果子节点的父节点ID等于父节点的ID
                    if (c.parentId== p.id) {
                        // 克隆子节点数组
                        let _child = JSON.parse(JSON.stringify(child));
                        // 从子节点数组中删除当前子节点
                        _child.splice(i, 1);
                        // 递归调用dataToTree函数,将当前子节点作为父节点,剩余的子节点作为子节点
                        dataToTree([c], _child);
                        // 如果父节点有children属性
                        if (p.children) {
                            // 将当前子节点添加到父节点的children数组中
                            p.children.push(c);
                        } else {
                            // 如果父节点没有children属性,则创建一个children数组,并将当前子节点添加到其中
                            p.children = [c];
                        }
                    }
                });
            });
        }
        return parentList;
    }

方法二:使用map节点映射

    //根据 parentId 和 id 构造树结构
    const buildTreeStructures = (array) => {
        // 创建一个map,用于存储每个节点的信息
        const map = {};
        // 创建一个roots数组,用于存储根节点
        const roots = [];
        // 遍历数组,将每个节点存储到map中
        array.forEach((node) => {
            map[node.id] = { ...node, children: [] };
        });

        // 再次遍历数组,将每个节点添加到其父节点的children数组中
        array.forEach((node) => {
            if (node.parentId&& node.parentId!='') {
                if (map[node.parentId]) {
                    map[node.parentId].children.push(map[node.id]);
                }
            } else {
                // 如果节点没有父节点,则将其添加到roots数组中
                roots.push(map[node.id]);
            }
        });
        // 返回根节点数组
        return roots;
    };

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值