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资料toString 方法
Mar 13 Javascript
如何做到打开一个页面,过几分钟自动转到另一页面
Apr 20 Javascript
jQuery 动画弹出窗体支持多种展现方式
Apr 29 Javascript
网页加载时页面显示进度条加载完成之后显示网页内容
Dec 23 Javascript
jquery实现表格奇数偶数行不同样式(有图为证及实现代码)
Jan 23 Javascript
js/jQuery对象互转(快速操作dom元素)
Feb 04 Javascript
javascript移动开发中touch触摸事件详解
Mar 18 Javascript
vue如何集成raphael.js中国地图的方法示例
Aug 15 Javascript
Vue框架下引入ActiveX控件的问题解决
Mar 25 Javascript
在vue中获取微信支付code及code被占用问题的解决方法
Apr 16 Javascript
微信小程序class封装http代码实例
Aug 24 Javascript
js 将多个对象合并成一个对象 assign方法的实现
Sep 24 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
咖啡知识大全
2021/03/03 新手入门
Swoole-1.7.22 版本已发布,修复PHP7相关问题
2015/12/31 PHP
php实现基于openssl的加密解密方法
2016/09/30 PHP
PHP的PDO事务与自动提交
2019/01/24 PHP
JS实现匀速运动的代码实例
2013/11/29 Javascript
JS+DIV+CSS实现仿表单下拉列表效果
2015/08/18 Javascript
Bootstrap在线电子商务网站实战项目5
2016/10/14 Javascript
Require.JS中的几种define定义方式示例
2017/06/01 Javascript
深究AngularJS中$sce的使用
2017/06/12 Javascript
angularjs2中父子组件的数据传递的实例代码
2017/07/05 Javascript
详解vue.js+UEditor集成 [前后端分离项目]
2017/07/07 Javascript
微信小程序实现评论功能
2018/11/28 Javascript
简单了解Ajax表单序列化的实现方法
2019/06/14 Javascript
Layui Form 自定义验证的实例代码
2019/09/14 Javascript
vue项目配置使用flow类型检查的步骤
2020/03/18 Javascript
[01:02]DOTA2辉夜杯决赛日 CDEC.Y对阵VG赛前花絮
2015/12/27 DOTA
[42:32]Secret vs Optic 2018国际邀请赛小组赛BO2 第二场 8.18
2018/08/19 DOTA
python读取浮点数和读取文本文件示例
2014/05/06 Python
Mac 上切换Python多版本
2017/06/17 Python
详解python多线程、锁、event事件机制的简单使用
2018/04/27 Python
Python实现抓取HTML网页并以PDF文件形式保存的方法
2018/05/08 Python
python 画三维图像 曲面图和散点图的示例
2018/12/29 Python
Python功能点实现:函数级/代码块级计时器
2019/01/02 Python
Python常用特殊方法实例总结
2019/03/22 Python
python接口自动化(十六)--参数关联接口后传(详解)
2019/04/16 Python
利用 Flask 动态展示 Pyecharts 图表数据方法小结
2019/09/04 Python
python 读取串口数据的示例
2020/11/09 Python
亚马逊海外购:亚马逊美国、英国、日本、德国直邮
2021/03/18 全球购物
Ajax和javascript的区别
2013/07/20 面试题
外贸英语专业求职信范文
2013/12/25 职场文书
高中政治教学反思
2014/01/18 职场文书
健康状况证明模板
2014/10/23 职场文书
初中体育课教学反思
2016/02/16 职场文书
导游词之江南园林狮子林
2019/09/16 职场文书
彻底理解golang中什么是nil
2021/04/29 Golang
一文搞懂Golang 时间和日期相关函数
2021/12/06 Golang