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 格式字符串的应用
Mar 29 Javascript
不得不分享的JavaScript常用方法函数集(上)
Dec 23 Javascript
完全深入学习Bootstrap表单
Nov 28 Javascript
js实现一个猜数字游戏
Mar 31 Javascript
Bootstrap Table使用整理(三)
Jun 09 Javascript
vuejs手把手教你写一个完整的购物车实例代码
Jul 06 Javascript
详解Vue学习笔记入门篇之组件的内容分发(slot)
Jul 17 Javascript
简单实现jQuery轮播效果
Aug 18 jQuery
javascript trie前缀树的示例
Jan 29 Javascript
解决vue 退出动画无效的问题
Aug 09 Javascript
JavaScript事件概念详解(区分静态注册和动态注册)
Feb 05 Javascript
vue使用refs获取嵌套组件中的值过程
Mar 31 Vue.js
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
Windows下IIS6/Apache2.2.4+MySQL5.2+PHP5.2.1安装配置方法
2007/05/03 PHP
PHP Squid中可缓存的动态网页设计
2008/09/17 PHP
PHP var_dump遍历对象属性的函数与应用代码
2010/06/04 PHP
php class中self,parent,this的区别以及实例介绍
2013/04/24 PHP
PHP获取文件夹内文件数的方法
2015/03/12 PHP
php利用ffmpeg提取视频中音频与视频画面的方法详解
2017/06/07 PHP
YII2自动登录Cookie总是失效的解决方法
2017/06/28 PHP
PHP重载基础知识回顾
2020/09/10 PHP
Nigma vs Alliance BO5 第一场2.14
2021/03/10 DOTA
TopList标签和JavaScript结合两例
2007/08/12 Javascript
JavaScript更改class和id的方法
2008/10/10 Javascript
实现连缀调用的map方法(prototype)
2009/08/05 Javascript
javascript URL编码和解码使用说明
2010/04/12 Javascript
javascript 全等号运算符使用说明
2010/05/31 Javascript
jquery 新浪网易的评论块制作
2010/07/01 Javascript
JQuery中使用.each()遍历元素学习笔记
2014/11/08 Javascript
在JavaScript中处理字符串之link()方法的使用
2015/06/08 Javascript
jquery实现鼠标经过显示下划线的渐变下拉菜单效果代码
2015/08/24 Javascript
JavaScript使用DeviceOne开发实战(四)仿优酷视频应用
2015/12/02 Javascript
JavaScript的Ext JS框架中的GridPanel组件使用指南
2016/05/21 Javascript
Bootstrap轮播图学习使用
2017/02/10 Javascript
JavaScript基本类型值-Number类型
2017/02/24 Javascript
javascript数据结构之串的概念与用法分析
2017/04/12 Javascript
vue+element-ui实现表格编辑的三种实现方式
2018/10/31 Javascript
[46:21]Liquid vs LGD 2018国际邀请赛淘汰赛BO3 第一场 8.23
2018/08/24 DOTA
pyinstaller还原python代码过程图解
2020/01/08 Python
Python运行提示缺少模块问题解决方案
2020/04/02 Python
Pycharm 2020.1 版配置优化的详细教程
2020/08/07 Python
Django model class Meta原理解析
2020/11/14 Python
美国鞋类购物网站:Shiekh Shoes
2016/08/21 全球购物
总经理职责范文
2013/11/08 职场文书
校园十佳歌手策划书
2014/01/22 职场文书
护士自我评价范文
2014/01/25 职场文书
《锄禾》教学反思
2014/04/08 职场文书
nginx location中多个if里面proxy_pass的方法
2021/03/31 Servers
Java实现多文件上传功能
2021/06/30 Java/Android