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 相关文章推荐
百度Popup.js弹出框进化版 拖拽小框架发布 兼容IE6/7/8,Firefox,Chrome
Apr 13 Javascript
使用jquery实现IE下按backspace相当于返回操作
Mar 18 Javascript
处理文本部分内容的TextRange对象应用实例
Jul 29 Javascript
JavaScript获取网页表单提交方式的方法
Apr 02 Javascript
js和jquery中获取非行间样式
May 05 jQuery
详解vue2.0 不同屏幕适配及px与rem转换问题
Feb 23 Javascript
node.js利用socket.io实现多人在线匹配联机五子棋
May 31 Javascript
vue.js实现的幻灯片功能示例
Jan 18 Javascript
小程序实现搜索框
Jun 19 Javascript
JS+CSS实现3D切割轮播图
Mar 21 Javascript
js实现车辆管理系统
Aug 26 Javascript
JS实现小米轮播图
Sep 21 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
全国FM电台频率大全 - 26 西藏自治区
2020/03/11 无线电
php修改时间格式的代码
2011/05/29 PHP
关于PHPDocument 代码注释规范的总结
2013/06/25 PHP
php的dl函数用法实例
2014/11/06 PHP
PHP正则验证Email的方法
2015/06/15 PHP
Laravel 5.3 学习笔记之 错误&amp;日志
2016/08/28 PHP
利用PHP将图片转换成base64编码的实现方法
2016/09/13 PHP
PHP实现正则表达式分组捕获操作示例
2018/02/03 PHP
基于laravel-admin 后台 列表标签背景的使用方法
2019/10/03 PHP
jquery.blockUI.js上传滚动等待效果实现思路及代码
2013/03/18 Javascript
javascript的parseFloat()方法精度问题探讨
2013/11/26 Javascript
js使用html()或text()方法获取设置p标签的显示的值
2014/08/01 Javascript
js监听鼠标点击和键盘点击事件并自动跳转页面
2014/09/24 Javascript
javascript 原型链维护和继承详解
2014/11/26 Javascript
js实现下拉框选择要显示图片的方法
2015/02/16 Javascript
Flash图片上传组件 swfupload使用指南
2015/03/14 Javascript
JavaScript中的acos()方法使用详解
2015/06/14 Javascript
多种方式实现js图片预览
2016/12/12 Javascript
node.js连接MongoDB数据库的2种方法教程
2017/05/17 Javascript
详解VUE2.X过滤器的使用方法
2018/01/11 Javascript
基于Node.js实现压缩和解压缩的方法
2018/02/13 Javascript
Vue-路由导航菜单栏的高亮设置方法
2018/03/17 Javascript
深入浅析Vue 中 ref 的使用
2019/04/29 Javascript
vue-router 按需加载 component: () =&gt; import() 报错的解决
2020/09/22 Javascript
python常见数制转换实例分析
2015/05/09 Python
Python迭代器定义与简单用法分析
2018/04/30 Python
Python代码实现http/https代理服务器的脚本
2019/08/12 Python
python实现的登录与提交表单数据功能示例
2019/09/25 Python
关于torch.optim的灵活使用详解(包括重写SGD,加上L1正则)
2020/02/20 Python
Django filter动态过滤与排序实现过程解析
2020/11/26 Python
BeautifulSoup中find和find_all的使用详解
2020/12/07 Python
MATCHESFASHION澳大利亚/亚太地区:英国时尚奢侈品电商
2020/01/14 全球购物
小学学习雷锋活动总结
2014/07/03 职场文书
群众路线党员自我评议范文2014
2014/09/24 职场文书
css3 实现文字闪烁效果的三种方式示例代码
2021/04/25 HTML / CSS
Vue elementUI表单嵌套表格并对每行进行校验详解
2022/02/18 Vue.js