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 globalStorage类代码
Jun 04 Javascript
js算法中的排序、数组去重详细概述
Oct 14 Javascript
jquery中使用循环下拉菜单示例代码
Sep 24 Javascript
详谈javascript中的cookie
Jun 03 Javascript
js实现String.Fomat的实例代码
Sep 02 Javascript
Node.js测试中的Mock文件系统详解
Nov 21 Javascript
JavaScript实现星星等级评价功能
Mar 22 Javascript
Node.JS利用PhantomJs抓取网页入门教程
May 19 Javascript
js原生实现移动端手指滑动轮播图效果的示例
Jan 02 Javascript
使用vue for时为什么要key【推荐】
Jul 11 Javascript
vue eslint简要配置教程详解
Jul 26 Javascript
vue实现手机端省市区区域选择
Sep 27 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写的采集程序
2007/03/16 PHP
PHP类与对象中的private访问控制的疑问
2012/11/01 PHP
php mysql 封装类实例代码
2016/09/18 PHP
Yii2.0多文件上传实例说明
2017/07/24 PHP
15个款优秀的 jQuery 图片特效插件推荐
2011/11/21 Javascript
jquery实现点击TreeView文本父节点展开/折叠子节点
2013/01/10 Javascript
批量实现面向对象的实例代码
2013/07/01 Javascript
jquery 实现密码框的显示与隐藏示例代码
2013/09/18 Javascript
JS OffsetParent属性深入解析
2014/01/13 Javascript
javascript数据类型示例分享
2015/01/19 Javascript
JavaScript知识点整理
2015/12/09 Javascript
jQuery隐藏和显示效果实现
2016/04/06 Javascript
基于WebUploader的文件上传js插件
2016/08/19 Javascript
AngularJS实现在ng-Options加上index的解决方法
2016/11/03 Javascript
jquery.multiselect多选下拉框实现代码
2016/11/11 Javascript
使用JavaScript实现一个小程序之99乘法表
2017/09/21 Javascript
Vue+SpringBoot开发V部落博客管理平台
2017/12/27 Javascript
JS计算输出100元钱买100只鸡问题的解决方法
2018/01/04 Javascript
JavaScript 有用的代码片段和 trick
2018/02/22 Javascript
使用vuex缓存数据并优化自己的vuex-cache
2018/05/30 Javascript
Vue实现本地购物车功能
2018/12/05 Javascript
[06:44]2018DOTA2亚洲邀请赛4.5 SOLO赛 MidOne vs Sumail
2018/04/06 DOTA
Python3基础之list列表实例解析
2014/08/13 Python
Python实现简单遗传算法(SGA)
2018/01/29 Python
python如何发布自已pip项目的方法步骤
2018/10/09 Python
详解Django-restframework 之频率源码分析
2019/02/27 Python
PYTHON实现SIGN签名的过程解析
2019/10/28 Python
python中的RSA加密与解密实例解析
2019/11/18 Python
python中的数组赋值与拷贝的区别详解
2019/11/26 Python
python实现从wind导入数据
2019/12/03 Python
详解Python中openpyxl模块基本用法
2021/02/23 Python
收集的22款给力的HTML5和CSS3帮助工具
2012/09/14 HTML / CSS
Pop In A Box英国:Funko POP搪胶公仔
2019/05/27 全球购物
前台接待岗位职责
2013/12/03 职场文书
优秀员工评语
2014/02/10 职场文书
Python数据结构之队列详解
2022/03/21 Python