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 Title、alt提示(Tips)实现源码解读
Dec 12 Javascript
jQuery写的日历(包括日历的样式及功能)
Apr 23 Javascript
js基础知识(公有方法、私有方法、特权方法)
Nov 06 Javascript
关于微信中a链接无法跳转问题
Aug 02 Javascript
js 将input框中的输入自动转化成半角大写(税号输入框)
Feb 16 Javascript
node跨域请求方法小结
Aug 25 Javascript
javascript如何用递归写一个简单的树形结构示例
Sep 06 Javascript
AngualrJs清除定时器遇到的坑
Oct 13 Javascript
使用JS中的Replace()方法遇到的问题小结
Oct 20 Javascript
微信小程序实现保存图片到相册功能
Nov 30 Javascript
JavaScript如何获取一个元素的样式信息
Jul 29 Javascript
js实现窗口全屏示例详解
Sep 17 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
第六节 访问属性和方法 [6]
2006/10/09 PHP
php数组转成json格式的方法
2015/03/09 PHP
tp5.1 框架数据库高级查询技巧实例总结
2020/05/25 PHP
js获取RadioButtonList的Value/Text及选中值等信息实现代码
2013/03/05 Javascript
Jquery 模拟用户点击超链接或者按钮的方法
2013/10/25 Javascript
JavaScript中九种常用排序算法
2014/09/02 Javascript
jQuery中empty()方法用法实例
2015/01/16 Javascript
Jquery 实现图片轮换
2015/01/28 Javascript
JavaScript中switch语句的用法详解
2015/06/03 Javascript
基于replaceChild制作简单的吞噬特效
2015/09/21 Javascript
JavaScript实现点击按钮直接打印
2016/01/06 Javascript
JS拖拽组件学习使用
2016/01/19 Javascript
JS通过Cookie判断页面是否为首次打开
2016/02/05 Javascript
javascript基本算法汇总
2016/03/09 Javascript
Angular.js与Bootstrap相结合实现表格分页代码
2016/04/12 Javascript
AngularJS中的表单简单入门
2016/07/28 Javascript
jQuery实现大图轮播
2017/02/13 Javascript
Vue2几种常见开局方式详解
2017/09/09 Javascript
js数组实现权重概率分配
2017/09/12 Javascript
VUE前端cookie简单操作
2017/10/17 Javascript
vue动态设置img的src路径实例
2018/09/18 Javascript
nvm、nrm、npm 安装和使用详解(小结)
2019/01/17 Javascript
今天,小程序正式支持 SVG
2019/04/20 Javascript
javascript使用Blob对象实现的下载文件操作示例
2020/04/18 Javascript
[01:08:48]LGD vs OG 2018国际邀请赛淘汰赛BO3 第三场 8.25
2018/08/29 DOTA
简单总结Python中序列与字典的相同和不同之处
2016/01/19 Python
Django框架安装方法图文详解
2019/11/04 Python
django 文件上传功能的相关实例代码(简单易懂)
2020/01/22 Python
解析Python 偏函数用法全方位实现
2020/06/26 Python
html5新特性与用法大全
2018/09/13 HTML / CSS
菲律宾购物网站:Lazada菲律宾
2018/04/05 全球购物
公司股权转让协议书
2014/04/12 职场文书
学生安全责任书
2014/04/15 职场文书
优秀学生干部个人事迹材料
2014/06/02 职场文书
2014年九一八事变演讲稿
2014/09/14 职场文书
mysql字符串截取函数小结
2021/04/05 MySQL