当前位置: 首页 > news >正文

【前端手撕】数组转树

把平铺的数组结构转换为树结构。

const arr = [ { id: "01", name: "张大大", pid: "", job: "项目经理" }, { id: "02", name: "小亮", pid: "01", job: "产品leader" }, { id: "03", name: "小美", pid: "01", job: "UIleader" }, { id: "04", name: "老马", pid: "01", job: "技术leader" }, { id: "05", name: "老王", pid: "01", job: "测试leader" }, { id: "06", name: "老李", pid: "01", job: "运维leader" }, { id: "07", name: "小丽", pid: "02", job: "产品经理" }, { id: "08", name: "大光", pid: "02", job: "产品经理" }, { id: "09", name: "小高", pid: "03", job: "UI设计师" }, { id: "10", name: "小刘", pid: "04", job: "前端工程师" }, { id: "11", name: "小华", pid: "04", job: "后端工程师" }, { id: "12", name: "小李", pid: "04", job: "后端工程师" }, { id: "13", name: "小赵", pid: "05", job: "测试工程师" }, { id: "14", name: "小强", pid: "05", job: "测试工程师" }, { id: "15", name: "小涛", pid: "06", job: "运维工程师" }, ];

转换为:

[ { id: "01", name: "张大大", pid: "", job: "项目经理", children: [ { id: "02", name: "小亮", pid: "01", job: "产品leader", children: [ { id: "07", name: "小丽", pid: "02", job: "产品经理", children: [] }, { id: "08", name: "大光", pid: "02", job: "产品经理", children: [] } ] }, // ... 其他子节点 ] } ]

暴力递归

function toTree(list, parId = '') { let len = list.length function loop(parId) { let res = [] // 存当前层的所有子节点 // 递归遍历整个数组,找到当前层所有子节点(注意:每次都是遍历全部) for (let i = 0; i < len; i++) { if (list[i].pid === parId) { // 如果当前项的父id是parId,说明是当前层的子节点 // 递归调用loop函数,找到当前项的所有子节点 list[i].children = loop(list[i].id) // 把当前节点(带着它的children)放入结果 res.push(list[i]) } } return res } return loop(parId) }

因为每次递归都是遍历整个数组,所以时间复杂度是O(n²),数据量大的时候会很慢。

遍历数组其实是为了找到父节点对应的子节点,并进行组装。因此可以先用map来做一次映射,方便父子节点的快速定位和组装。优化为用哈希来解:

哈希解法

function toTreeHash(list) { const res = [] const map = {} // 先把所有项都放到哈希表中,浅拷贝不污染原数组 arr.forEach(item => map[item.id] = {...item, children:[]}) // 遍历数组,根据父id找到子节点,把子节点放到父节点的children数组中 for (let item of list) { let node = map[item.id] if (item.pid) { // 避免父节点不存在的情况导致报错 if (!map[item.pid]) continue // 把当前项放到父节点的children数组中 map[item.pid].children.push(node) } else { // 没有父id,说明是根节点 res.push(node) } } return res }

因为只遍历两次数组,时间复杂度为O(n)

http://www.jsqmd.com/news/1055618/

相关文章:

  • Betaflight Configurator终极指南:三步掌握无人机飞控调参核心技巧
  • 2026安徽中考落榜,考不上普高还有学校读(重点推荐) - 小张zc
  • 2026 年本质阻燃面料行业深度解析:晶臻碳纶新材打破高温防护壁垒,多场景选型与厂家对比指南 - 资讯速览
  • 5分钟免费激活Windows和Office:KMS_VL_ALL_AIO智能激活解决方案终极指南
  • 多语言文本嵌入模型在仇恨言论检测中的性能评估与实战指南
  • 2026年众智商学院SCMP供应链主管备考怎么选模块?采购物流计划岗位按3+1、3+2和3+3组合建议 - 众智商学院职业教育
  • 新乡黄金回收怎么选不踩坑?本地正规变现门店推荐 - 百航
  • MusicPlayer2:Windows平台终极开源音乐播放器完全指南
  • RPG Maker Decrypter完整指南:5分钟学会解密RPG游戏资源
  • MC68HC908MR24电机控制MCU:从引脚、内存到FLASH编程的实战解析
  • 最新发布:2026年宿州单招落榜了怎么办?一年复读冲公办,82分就能保底! - 小张zc
  • Kinetis M代码分离:嵌入式系统功能安全与内存隔离实践
  • 4、SpringBoot框架集成Kafka
  • 重磅|2026年法穆兰官方维修中心新址全新升级,服务热线同步启用 - 亨得利中国服务中心
  • 血压监测设备中ADC精度提升实战:从过采样到系统校准
  • 3步实现美的智能家居设备本地化控制方案
  • 亳州黄金贵金属回收优选指南:六家靠谱门店覆盖全城 - 清奢黄金上门回收
  • 2026年雅典官方售后服务体系升级公告:全新官方维修门店新址升级落地,最新服务热线同步开通 - 亨得利中国服务中心
  • 2026年法穆兰官方售后服务中心新址揭晓|全国网点更新,全新服务热线同步公示 - 亨得利中国服务中心
  • 2026年河东区游泳馆五大排名:水质、价格、教练对比 - 资讯速览
  • 实现4S完整策略历史回测程序,输出年化收益,最大回撤核心指标。
  • 安乐镇汽车汽修厂怎么选?靠谱维保认准程金汽车维修 - 百航
  • 东营黄金贵金属回收|六家靠谱店铺全城推荐 - 新芸鼎珠宝首饰
  • Python开发进阶之路:构建高性能数据处理系统
  • 当AI遇见中医:仲景大语言模型的破局之路
  • 2026 年 6 月精工官方服务中心实地走访核验报告:全国 60 余家门店地址全面更新 - 亨得利腕表服务中心
  • 大理汽车贴膜怎么选?领秀汽车贴膜3M优势详解 - 百航
  • MMA8450Q加速度计:高通滤波与瞬态检测实战指南
  • Ubuntu 12.10 编译安装 Nginx 1.4.7 完整指南
  • ScottPlot实战指南:5种高效图表导出方案与PDF集成技巧