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----文件操作
Jan 18 Javascript
jQuery学习笔记之控制页面实现代码
Feb 27 Javascript
关于js中alert弹出窗口文本换行问题简单详细说明
Dec 11 Javascript
纯js网页画板(Graphics)类简介及实现代码
Dec 24 Javascript
js 三级关联菜单效果实例
Aug 13 Javascript
javascript 判断字符串是否包含某字符串及indexOf使用示例
Oct 18 Javascript
JS中使用Array函数shift和pop创建可忽略参数的例子
May 28 Javascript
浅谈Node.js:fs文件系统模块
Dec 08 Javascript
Vue 2.0+Vue-router构建一个简单的单页应用(附源码)
Mar 14 Javascript
JS点击动态添加标签、删除指定标签的代码
Apr 18 Javascript
vue升级之路之vue-router的使用教程
Aug 14 Javascript
Vue实现本地购物车功能
Dec 05 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魔术变量用法实例详解
2014/11/13 PHP
关于PHP开发的9条建议
2015/07/27 PHP
简单了解将WordPress中的工具栏移到底部的小技巧
2015/12/31 PHP
读jQuery之八 包装事件对象
2011/06/21 Javascript
jQuery学习笔记之基础中的基础
2015/01/19 Javascript
JavaScript实现的一个倒计时的类
2015/03/12 Javascript
js实现的二分查找算法实例
2016/01/21 Javascript
第一次接触神奇的Bootstrap导航条
2016/08/09 Javascript
分享JS代码实现鼠标放在输入框上输入框和图片同时更换样式
2016/09/01 Javascript
使用异步组件优化Vue应用程序的性能
2019/04/28 Javascript
nodejs通过钉钉群机器人推送消息的实现代码
2019/05/05 NodeJs
JS运算符优先级与表达式示例详解
2020/09/04 Javascript
Python3.7实现中控考勤机自动连接
2018/08/28 Python
Python增强赋值和共享引用注意事项小结
2019/05/28 Python
Python+Selenium使用Page Object实现页面自动化测试
2019/07/14 Python
解决python多行注释引发缩进错误的问题
2019/08/23 Python
python单例模式原理与创建方法实例分析
2019/10/26 Python
win10下python2和python3共存问题解决方法
2019/12/23 Python
浅谈tensorflow之内存暴涨问题
2020/02/05 Python
使用Python和百度语音识别生成视频字幕的实现
2020/04/09 Python
Python Django中间件使用原理及流程分析
2020/06/13 Python
浅谈Django前端后端值传递问题
2020/07/15 Python
Django框架安装及项目创建过程解析
2020/09/14 Python
美国销售第一的智能手机和平板电脑保护壳:OtterBox
2017/12/21 全球购物
澳大利亚婴儿礼品公司:The Baby Gift Company
2018/11/04 全球购物
网站域名和主机:Domain.com
2019/04/01 全球购物
Hotels.com越南:酒店预订
2019/10/29 全球购物
Nasty Gal英国:美国女性服饰销售网站
2021/03/02 全球购物
土木工程毕业生自荐信
2013/11/12 职场文书
发展党员工作情况汇报
2014/10/28 职场文书
房产公证书
2015/01/23 职场文书
北大自主招生自荐信
2015/03/04 职场文书
物业工程部经理岗位职责
2015/04/09 职场文书
中学综治宣传月活动总结
2015/05/07 职场文书
2016党员入党决心书
2015/09/22 职场文书
商业计划书之服装
2019/09/09 职场文书