js包含层级关系的一维数组转化成树状结构数组

本文介绍如何将带有parentId字段的扁平数据数组转换为树形结构数据,通过递归函数实现,适用于层数及每层数据条数不定的情况。提供两种方法,一种直接递归查找子节点,另一种先过滤出顶级节点再递归构建子节点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

//例 
//层数不定 每一层数据条数不定
let arr = [
 {id: 1, parentId: ''},
 {id: 2, parentId: 1},
 {id: 3, parentId: 2}
]
//需要转化成
newArr = [
 {
  id: 1, 
  parentId: '', 
  children: [
    {
      id: 2,
      parentId: 1,
      children: [
        {
          id: 3,
          parentId: 2
        }
      ]
    }
  ]
 }
]

//代码实现
//法一
//parentId默认值为''
function translateDataToTree(data, parentId = '') {
  let tree = [];
  let temp;
  data.forEach((item, index) => {
    if (data[index].parentId == parentId) {
      let obj = data[index];
      temp = translateDataToTree(data, data[index].id);
      if (temp.length > 0) {
        obj.children = temp;
      }
      tree.push(obj);
    }
  })
  return tree;
}

//法二
function translateDataToTree(array) {
  //第一层数据
  let parents = array.filter(item => item.parentId === "");
  //有父节点的数据
  let childrens = array.filter(item => item.parentId !== "");
  function translator(parents, childrens) {
    parents.forEach( parent => {
      childrens.forEach( (children, index) => {
        //找到子层的父层
        if (children.parentId === parent.id) {
          //temp 这步不是必须
          //对子节点数据进行深复制
          let temp = JSON.parse(JSON.stringify(childrens));
          //让当前子节点从temp中移除,temp作为新的子节点数据,这里是为了让递归时,子节点的遍历次数更少,如果父子关系的层级越多,越有利
          temp.splice(index, 1);
          //判断是否有children属性 有就直接push 没有就增加children属性
          parent.children ? parent.children.push(children) : parent.children = [children];
          //不用temp 传childrens也可
          translator([children], temp);
        }
      })
    })
  }
  translator(parents, childrens);
  //返回最终结果
  return parents;
}

最主要的是递归的使用

第二种方式使用map

function arrayToTree(arr) {
  const idMap = new Map()
  const result = []

  // 初始化 Map
  arr.forEach((item) => {
    idMap.set(item.id, { ...item, children: [] })
  })

  // 构建树
  arr.forEach((item) => {
    const parent = idMap.get(item.parentId)
    if (parent) {
      parent.children.push(idMap.get(item.id))
    } else {
      result.push(idMap.get(item.id))
    }
  })

  return result
}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值