JavaScript将列表转为树

本文介绍了一种使用JavaScript将扁平化的数据转换成树形结构的方法,包括两种实现方式:使用双重for循环和利用数组对象的方法。同时探讨了引用类型数据在这一过程中的作用。

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

先说一下需求是什么意思,假设有下面的一组数据: 

var list = [
  { id: 1013, pid: 0 },
  { id: 1014, pid: 0 },
  { id: 1061, pid: 1013 },
  { id: 1063, pid: 1014 },
  { id: 1066, pid: 1014 },
  { id: 1067, pid: 1066 }
]

现在要把它转为下面这样的树形结构:

var tree = [
  { id: 1013, pid: 0, children: [
    { id: 1061, pid: 1013 }
  ]}, 
  { id: 1014, pid: 0, children: [
    { id: 1063, pid: 1014 },
    { id: 1066, pid: 1014, children: [
      { id: 1067, pid: 1066 }
    ]}
  ]}
]
  • 用 for 循环的方式

// 用for循环的方法
for (var i = 0; i < list.length; i++) {
  for (var j = 0; j < list.length; j++) {
    // 如果有父节点
    if (list[i].pid === list[j].id) {
      // 放进它父节点的children数组中;如果children不存在,初始化为空数组
      list[j].children = list[j].children || []
      list[j].children.push(list[i])
      // 因为每个节点至多有一个父节点,所以这里可以退出本次循环,避免无z意义的运算
      break
    }
  }
  // 如果j的值等于list的长度,说明在内层循环中没有触发break,也就是说这个节点是根节点
  if (j === list.length) tree.push(list[i])
}
  • 用数组对象中的方法
// filter筛选符合条件的元素,返回一个包含所有符合条件的元素的新数组
tree = list.filter(item1 => !list.find((item2, index) => {
  // 如果有父节点
  if (item1.pid === item2.id) {
    // 放进它父节点的children数组中;如果children不存在,初始化为空数组
    list[index].children = list[index].children || []
    list[index].children.push(item1)
  }
  // find返回第一个符合条件的元素,找到后,剩余的元素不再判断
  return item1.pid === item2.id
}))

关于 filterfind,详细信息可以到 MDN 查看

 解读

以上两个方法都利用了引用类型数据的特点,当我们创建一个保存引用类型数据的变量时,实际上我们保存的是它在内存中的地址,如果你的入门语言是 C,那么你一定对指针不陌生,JavaScript 的引用类型在这一点上与 C 的指针类似。

上面的代码中,每次向 children 中 push 数据时,我们 push 的都是“地址”,所以只需要通过一次遍历,将所有非根节点放到它的父节点中,就能得到树形结构。

可以看到,上面的代码都对原数据 list 做了操作,如果不想改变原数据,需要对 list 进行深拷贝,直接这样写是没有用的:

var tree = list

原因正是上面提到的引用类型,如何做深拷贝,那就是另一个故事了。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值