js实现树形数据转成扁平数据的方法示例


Posted in Javascript onFebruary 27, 2020

利用递归的方法循环树形数组,当遇到有children的对象再次调用递归函数循环children数组,每次循环的数据放入一个提前声明好的数组里,等所有递归函数执行完,这个数组即是想要得到的扁平数据数组。

let res = []
const fn = (source)=>{
 source.forEach(el=>{
  res.push(el)
  el.children && el.children.length>0 ? fn(el.children) : ""
 })
}

示例1

let res = []  // 用于存储递归结果(扁平数据)
// 递归函数
const fn = (source)=>{
 source.forEach(el=>{
  res.push(el)
  el.children && el.children.length>0 ? fn(el.children) : ""  // 子级递归
 })
}
 
// 树形数据
const arr = [
 { id: "1", rank: 1 },
 { id: "2", rank: 1,
  children:[ 
   { id: "2.1", rank: 2 },
   { id: "2.2", rank: 2 } 
  ] 
 },
 { id: "3", rank:1,
  children:[ 
   { id: "3.1", rank:2, 
    children: [ 
     { id:'3.1.1', rank:3,
      children:[ 
       { id: "3.1.1.1", rank: 4, 
        children:[
         { id: "3.1.1.1.1", rank: 5 }
        ] 
       } 
      ] 
     } 
    ] 
   } 
  ] 
 }
]
 
fn(arr)    // 执行递归函数
console.log(res) // 查看结果

结果:

js实现树形数据转成扁平数据的方法示例

查看源码 

扁平数据转成树形数据,请参考这篇文章:js实现无限层级树形数据结构(创新算法)

js将扁平结构数据转换为树形结构

递归实现

function transformTree (list) {
 const tree = []
 
 for (let i = 0, len = list.length; i < len; i++) {
  if (!list[i].pid) {
   const item = queryChildren(list[i], list)
   
   tree.push(item)
  }
 }
 
 return tree
}

function queryChildren (parent, list) {
 const children = []
 
 for (let i = 0, len = list.length; i < len; i++) {
  if (list[i].pid === parent.id) {
   const item = queryChildren(list[i], list)

   children.push(item)
  }
 }
 
 if (children.length) {
  parent.children = children
 }
 
 return parent
}

尽管后续对上面的算法进行了很多优化,但是仍未离开递归,递归可能遇到的问题还是会有可能遇到

循环实现

随着进化,循环代替递归是必然的结果~

两次循环

开始使用循环实现时,使用了两次循环完成转换,先进行一次循环将数据转换成 map 结构,使其能通过 id 快速查询

function transformTree (list) {
 const tree = []
 const record = {}
 const length = list.length
 
 for (let i = 0; i < length; i++) {
  const item = list[i]
  
  item.children = [] // 重置 children
  record[item.id] = item
 }
 
 for (let i = 0; i < length; i++) {
  const item = list[i]
  
  if (item.pid) {
   if (record[item.pid]) {
    record[item.pid].children.push(item)
   }
  } else {
   tree.push(item)
  }
 }
 
 return tree
}

上面的算法相较于递归的实现,不存在栈溢出的问题,而且是线性复杂度,效率已经提高了许多

一次循环

再进行一定的优化,最后变成一次循环完成树形构建

function transformTree (list) {
 const tree = []
 const record = {}
 
 for (let i = 0, len = list.length; i < len; i++) {
  const item = list[i]
  const id = item.id
  
  if (record[id]) {
   item.children = record[id]
  } else {
   item.children = record[id] = []
  }
  
  if (item.pid) {
   if (!record[item.pid]) {
    record[item.pid] = []
   }
   
   record[item.pid].push(item)
  } else {
   tree.push(item)
  }
 }
}

使用对象变量的特性,使用 map 结构直接指向 children 数组,在循环中初始化的同时还能快速查找插入相应的 children 里,使其在一次循环内完成构建,最后附上完整版~

function transformTree (list, options = {}) {
 const {
  keyField = 'id',
  childField = 'children',
  parentField = 'parent'
 } = options

 const tree = []
 const record = {}

 for (let i = 0, len = list.length; i < len; i++) {
  const item = list[i]
  const id = item[keyField]

  if (!id) {
   continue
  }

  if (record[id]) {
   item[childField] = record[id]
  } else {
   item[childField] = record[id] = []
  }

  if (item[parentField]) {
   const parentId = item[parentField]

   if (!record[parentId]) {
    record[parentId] = []
   }

   record[parentId].push(item)
  } else {
   tree.push(item)
  }
 }

 return tree
}

到此这篇关于js实现树形数据转成扁平数据的方法示例的文章就介绍到这了,更多相关js 树形数据转成扁平数据内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
javascript中获取选中对象的类型
Apr 02 Javascript
Google 静态地图API实现代码
Nov 19 Javascript
基于jQuery的为attr添加id title等效果的实现代码
Apr 20 Javascript
js获取GridView中行数据的两种方法 分享
Jul 13 Javascript
jquery中插件实现自动添加用户的具体代码
Nov 15 Javascript
JQuery处理json与ajax返回JSON实例代码
Jan 03 Javascript
js简单实现标签云效果实例
Aug 06 Javascript
JS排序之选择排序详解
Apr 08 Javascript
bootstrap table实现x-editable的行单元格编辑及解决数据Empty和支持多样式问题
Aug 10 Javascript
详解在React-Native中持久化redux数据
May 22 Javascript
使用JavaScript获取扫码枪扫描得到的条形码的思路代码详解
Jun 10 Javascript
layui使用及简单的三级联动实现教程
Dec 01 Javascript
vue学习笔记之给组件绑定原生事件操作示例
Feb 27 #Javascript
ElementUI Tree 树形控件的使用并给节点添加图标
Feb 27 #Javascript
ElementUI中el-tree节点的操作的实现
Feb 27 #Javascript
element el-tree组件的动态加载、新增、更新节点的实现
Feb 27 #Javascript
element-ui table行点击获取行索引(index)并利用索引更换行顺序
Feb 27 #Javascript
微信小程序录音实现功能并上传(使用node解析接收)
Feb 26 #Javascript
BootStrap前端框架使用方法详解
Feb 26 #Javascript
You might like
php 分库分表hash算法
2009/11/12 PHP
php根据一个给定范围和步进生成数组的方法
2015/06/19 PHP
JavaScript 高级语法介绍
2009/06/15 Javascript
javascript下对于事件、事件流、事件触发的顺序随便说说
2010/07/17 Javascript
javascript 冒泡排序 正序和倒序实现代码
2010/12/14 Javascript
JS实现日期加减的方法
2013/11/29 Javascript
javascript图片切换综合实例(循环切换、顺序切换)
2016/01/13 Javascript
使用JS和canvas实现gif动图的停止和播放代码
2017/09/01 Javascript
vue系列之requireJs中引入vue-router的方法
2018/07/18 Javascript
详解操作虚拟dom模拟react视图渲染
2018/07/25 Javascript
微信小程序chooseImage的用法(从本地相册选择图片或使用相机拍照)
2018/08/22 Javascript
浅谈Vue render函数在ElementUi中的应用
2018/09/06 Javascript
Node.js npm命令运行node.js脚本的方法
2018/10/10 Javascript
通过vue手动封装on、emit、off的代码详解
2019/05/29 Javascript
JS实现拖拽元素时与另一元素碰撞检测
2020/08/27 Javascript
[01:57]2018DOTA2亚洲邀请赛赛前采访-iG
2018/04/03 DOTA
零基础写python爬虫之抓取糗事百科代码分享
2014/11/06 Python
老生常谈Python序列化和反序列化
2017/06/28 Python
django进阶之cookie和session的使用示例
2018/08/17 Python
python和mysql交互操作实例详解【基于pymysql库】
2019/06/04 Python
Python迭代器iterator生成器generator使用解析
2019/10/24 Python
python实现五子棋程序
2020/04/24 Python
Django中的AutoField字段使用
2020/05/18 Python
python中upper是做什么用的
2020/07/20 Python
用python制作个音乐下载器
2021/01/30 Python
LEGO玩具英国官方商店:LEGO Shop GB
2018/03/27 全球购物
Talbots官网:美国成熟女装品牌
2019/11/15 全球购物
毕业留言寄语大全
2014/04/10 职场文书
债务纠纷委托书
2014/08/30 职场文书
银行职员工作失误检讨书
2014/10/14 职场文书
2015年信息宣传工作总结
2015/05/26 职场文书
基层工作经历证明
2015/06/19 职场文书
运动会广播稿100字
2015/08/19 职场文书
小学英语新课改心得体会
2016/01/22 职场文书
MySQL 分组查询的优化方法
2021/05/12 MySQL
mysql查找连续出现n次以上的数字
2022/05/11 MySQL