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 继承的实现
Jul 09 Javascript
jquery异步调用页面后台方法&amp;#8207;(asp.net)
Mar 01 Javascript
JS关闭窗口与JS关闭页面的几种方法小结
Dec 17 Javascript
jQuery简单几行代码实现tab切换
Mar 10 Javascript
基于jquery实现select选择框内容左右移动添加删除代码分享
Aug 25 Javascript
javascript 动态脚本添加的简单方法
Oct 11 Javascript
JavaScript登录验证基础教程
Nov 01 Javascript
浅析JS抽象工厂模式
Dec 14 Javascript
Vue 理解之白话 getter/setter详解
Apr 16 Javascript
vue两组件间值传递 $router.push实现方法
May 15 Javascript
小程序云开发获取不到数据库记录的解决方法
May 18 Javascript
浅谈Vue 自动化部署打包上线
Jun 14 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的cURL库功能简介 抓取网页、POST数据及其他
2011/04/07 PHP
[原创]PHP字符串中插入子字符串方法总结
2016/05/06 PHP
php简单备份与还原MySql的方法
2016/05/09 PHP
php mysql like 实现多关键词搜索的方法
2016/10/29 PHP
PHP 获取指定地区的天气实例代码
2017/02/08 PHP
表单提交时自动复制内容到剪贴板的js代码
2007/03/16 Javascript
Javascript 调试利器 Firebug使用详解六
2009/07/05 Javascript
javascript 新浪背投广告实现代码
2009/07/07 Javascript
在服务端(Page.Write)调用自定义的JS方法详解
2013/08/09 Javascript
JS的encodeURI和java的URLDecoder.decode使用介绍
2014/05/08 Javascript
原生js仿jquery实现对Ajax的封装
2016/10/04 Javascript
浅谈js算法和流程控制
2016/12/29 Javascript
ES6学习教程之模板字符串详解
2017/10/09 Javascript
Vue前端判断数据对象是否为空的实例
2020/09/02 Javascript
解决antd Form 表单校验方法无响应的问题
2020/10/27 Javascript
Python在线运行代码助手
2016/07/15 Python
Zookeeper接口kazoo实例解析
2018/01/22 Python
python取数作为临时极大值(极小值)的方法
2018/10/15 Python
python requests.post带head和body的实例
2019/01/02 Python
浅谈Python大神都是这样处理XML文件的
2019/05/31 Python
Django 项目重命名的实现步骤解析
2019/08/14 Python
python+rsync精确同步指定格式文件
2019/08/29 Python
TensorFlow Saver:保存和读取模型参数.ckpt实例
2020/02/10 Python
Python龙贝格法求积分实例
2020/02/29 Python
django配置app中的静态文件步骤
2020/03/27 Python
使用Numpy对特征中的异常值进行替换及条件替换方式
2020/06/08 Python
CSS3 创建网页动画实现弹跳球动效果
2018/10/30 HTML / CSS
俄罗斯园林植物网上商店:Garshinka
2020/07/16 全球购物
物业管理大学生个人的自我评价
2013/10/10 职场文书
竞聘书格式及范文
2014/03/31 职场文书
伊琍体标语
2014/06/25 职场文书
应届生面试求职信
2014/07/02 职场文书
培训师岗位职责
2015/02/14 职场文书
学子宴致辞大全
2015/07/27 职场文书
python 中yaml文件用法大全
2021/07/04 Python
Python批量解压&压缩文件夹的示例代码
2022/04/04 Python