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 TO HTML 转换
Jun 26 Javascript
调试Node.JS的辅助工具(NodeWatcher)
Jan 04 Javascript
让javascript加载速度倍增的方法(解决JS加载速度慢的问题)
Dec 12 Javascript
javascript操作select元素实例分析
Mar 27 Javascript
js阻止浏览器默认行为的简单实例
May 15 Javascript
完美实现八种js焦点轮播图(上篇)
Jul 18 Javascript
js 提交form表单和设置form表单请求路径的实现方法
Oct 25 Javascript
js实现选项卡内容切换以及折叠和展开效果【推荐】
Jan 08 Javascript
微信小程序支付PHP代码
Aug 23 Javascript
ES6入门教程之变量的解构赋值详解
Apr 13 Javascript
详解Vue依赖收集引发的问题
Apr 22 Javascript
Node.js 中判断一个文件是否存在
Aug 24 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+AJAX实现无刷新注册(带用户名实时检测)
2006/12/02 PHP
Android ProgressBar进度条和ProgressDialog进度框的展示DEMO
2013/06/19 PHP
PHP中使用FFMPEG获取视频缩略图和视频总时长实例
2014/05/04 PHP
php实现按照权重随机排序数据的方法
2015/01/09 PHP
PHPStudy下如何为Apache安装SSL证书的方法步骤
2019/01/23 PHP
基础的prototype.js常用函数及其用法
2007/03/10 Javascript
关于JavaScript对象的动态选择及遍历对象
2014/03/10 Javascript
jquery实现的随机多彩tag标签随机颜色和字号大小效果
2014/03/27 Javascript
JS动态添加Table的TR,TD实现方法
2015/01/28 Javascript
JS中的二叉树遍历详解
2016/03/18 Javascript
jQuery ajax全局函数处理session过期后的ajax跳转问题
2016/06/03 Javascript
javaScript给元素添加多个class的简单实现
2016/07/20 Javascript
JS跨域请求外部服务器的资源
2017/02/06 Javascript
BootStrap与Select2使用小结
2017/02/17 Javascript
jQuery中map函数的两种方式
2017/04/07 jQuery
nodejs入门教程六:express模块用法示例
2017/04/24 NodeJs
解决iView中时间控件选择的时间总是少一天的问题
2018/03/15 Javascript
Vue SSR 组件加载问题
2018/05/02 Javascript
简单了解JavaScript异步
2019/05/23 Javascript
javascript json对象小技巧之键名作为变量用法分析
2019/11/11 Javascript
使用Python构建Hopfield网络的教程
2015/04/14 Python
用Python脚本来删除指定容量以上的文件的教程
2015/05/04 Python
Python selenium 三种等待方式详解(必会)
2016/09/15 Python
CentOS6.5设置Django开发环境
2016/10/13 Python
pandas删除指定行详解
2019/04/04 Python
Python 转换RGB颜色值的示例代码
2019/10/13 Python
详解Django CAS 解决方案
2019/10/30 Python
python pandas利用fillna方法实现部分自动填充功能
2020/03/16 Python
CSS3实现文本垂直排列的方法
2018/07/10 HTML / CSS
基于IE10/HTML5 开发
2013/04/22 HTML / CSS
Canvas高级路径操作之拖拽对象的实现
2019/08/05 HTML / CSS
瑞贝卡·泰勒官方网站:Rebecca Taylor
2016/09/24 全球购物
2014年两会学习心得体会
2014/03/10 职场文书
会计专业个人自我鉴定
2014/03/21 职场文书
标准的毕业生自荐信
2014/04/20 职场文书
uniapp引入支付宝原生扫码插件步骤详解
2022/07/23 Javascript