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 相关文章推荐
js利用Array.splice实现Array的insert/remove
Jan 13 Javascript
基于Jquery+Ajax+Json的高效分页实现代码
Oct 29 Javascript
简单js代码实现selece二级联动(推荐)
Feb 18 Javascript
jQuery实现仿美橙互联两级导航菜单的方法
Mar 09 Javascript
javascript中tostring()和valueof()的用法及两者的区别
Nov 16 Javascript
微信小程序自定义模态对话框实例详解
Aug 16 Javascript
浅谈Angularjs中不同类型的双向数据绑定
Jul 16 Javascript
js 实现在2d平面上画8的方法
Oct 10 Javascript
小程序实现长按保存图片的方法
Dec 31 Javascript
微信小程序实现二维码签到考勤系统
Jan 16 Javascript
swiper4实现移动端导航栏tab滑动切换
Oct 16 Javascript
jQuery实现放大镜案例
Oct 19 jQuery
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
Javascript Tab 导航插件 (23个)
2009/06/11 Javascript
jquery插件开发方法(初学者)
2012/02/03 Javascript
JQuery实现倒计时按钮具体方法
2013/11/14 Javascript
jQuery对于显示和隐藏等常用状态的判断方法
2014/12/13 Javascript
JavaScript常用字符串与数组扩展函数小结
2016/04/24 Javascript
javascript实现简单的on事件绑定
2016/08/23 Javascript
JS识别浏览器类型(电脑浏览器和手机浏览器)
2016/11/18 Javascript
微信小程序进行微信支付的步骤昂述
2016/12/01 Javascript
jQuery 选择符详细介绍及整理
2016/12/02 Javascript
JavaScript获取短信验证码(周期性)
2016/12/29 Javascript
Nodejs基于LRU算法实现的缓存处理操作示例
2017/03/17 NodeJs
JS与HTML结合实现流程进度展示条思路详解
2017/09/03 Javascript
js 计算图片内点个数的示例代码
2019/04/04 Javascript
如何从头实现一个node.js的koa框架
2019/06/17 Javascript
JavaScript深入V8引擎以及编写优化代码的5个技巧
2019/06/24 Javascript
微信小程序加载机制及运行机制图解
2019/11/27 Javascript
python pickle 和 shelve模块的用法
2013/09/16 Python
使用Python下载歌词并嵌入歌曲文件中的实现代码
2015/11/13 Python
Python实现递归遍历文件夹并删除文件
2016/04/18 Python
Python使用PyCrypto实现AES加密功能示例
2017/05/22 Python
使用pyecharts在jupyter notebook上绘图
2020/04/23 Python
Python上下文管理器和with块详解
2017/09/09 Python
python os.path模块常用方法实例详解
2018/09/16 Python
django+echart绘制曲线图的方法示例
2018/11/26 Python
Python爬虫学习之获取指定网页源码
2019/07/30 Python
Python中函数的返回值示例浅析
2019/08/28 Python
Python实现中值滤波去噪方式
2019/12/18 Python
python 浅谈serial与stm32通信的编码问题
2019/12/18 Python
css3实现图片遮罩效果鼠标hover以后出现文字
2013/11/05 HTML / CSS
CSS3 rgb and rgba(透明色)的使用详解
2020/09/25 HTML / CSS
房地产开盘策划方案
2014/02/10 职场文书
团日活动总结怎么写
2014/06/25 职场文书
委托书的写法
2014/08/30 职场文书
清明节扫墓活动总结
2015/02/09 职场文书
2019新员工试用期转正工作总结范文
2019/08/21 职场文书
你知道哪几种MYSQL的连接查询
2021/06/03 MySQL