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 相关文章推荐
判断是否输入完毕再激活提交按钮
Jun 26 Javascript
[Web]防止用户复制页面内容和另存页面的方法
Feb 06 Javascript
ko knockoutjs动态属性绑定技巧应用
Nov 14 Javascript
关于JS数组追加数组采用push.apply的问题
Jun 09 Javascript
js图片跟随鼠标移动代码
Nov 26 Javascript
javascript实现下拉提示选择框
Dec 29 Javascript
详解Angular.js指令中scope类型的几种特殊情况
Feb 21 Javascript
javascript 玩转Date对象(实例讲解)
Jul 11 Javascript
Bootstrap 模态框多次显示后台提交多次BUG的解决方法
Dec 26 Javascript
微信小程序自定义导航教程(兼容各种手机)
Dec 12 Javascript
JS实现电脑虚拟键盘打字测试
Jun 24 Javascript
uni-app 微信小程序授权登录的实现步骤
Feb 18 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实现获取客户端IP并获取IP信息
2015/03/17 PHP
Draggable Elements 元素拖拽功能实现代码
2011/03/30 Javascript
JS实现点击下载的小例子
2013/07/10 Javascript
js去除输入框中所有的空格和禁止输入空格的方法
2014/06/09 Javascript
jquery实现两个图片渐变切换效果的方法
2015/06/25 Javascript
JS+CSS实现的日本门户网站经典选项卡导航效果
2015/09/27 Javascript
延时加载JavaScript代码提高速度
2015/12/27 Javascript
浅析Javascript匿名函数与自执行函数
2016/02/06 Javascript
WebApi+Bootstrap+KnockoutJs打造单页面程序
2016/05/16 Javascript
JavaScript手机振动API
2016/06/11 Javascript
AngularJS入门教程之Scope(作用域)
2016/07/27 Javascript
JSON对象 详解及实例代码
2016/10/18 Javascript
浅谈struts1 &amp; jquery form 文件异步上传
2017/05/25 jQuery
深入浅出es6模板字符串
2017/08/26 Javascript
react 应用多入口配置及实践总结
2018/10/17 Javascript
nodejs微信开发之自动回复的实现
2019/03/17 NodeJs
Emberjs 通过 axios 下载文件的方法
2019/09/03 Javascript
[49:31]DOTA2-DPC中国联赛 正赛 Elephant vs LBZS BO3 第二场 1月29日
2021/03/11 DOTA
Anaconda2下实现Python2.7和Python3.5的共存方法
2018/06/11 Python
python实现多人聊天室
2020/03/31 Python
Python3获取电脑IP、主机名、Mac地址的方法示例
2019/04/11 Python
python学习--使用QQ邮箱发送邮件代码实例
2019/04/16 Python
python梯度下降算法的实现
2020/02/24 Python
基于opencv的selenium滑动验证码的实现
2020/07/24 Python
python selenium xpath定位操作
2020/09/01 Python
Python脚本打包成可执行文件过程解析
2020/10/20 Python
解决Pymongo insert时会自动添加_id的问题
2020/12/05 Python
PyCharm Ctrl+Shift+F 失灵的简单有效解决操作
2021/01/15 Python
HTML5的标签的代码的简单介绍 HTML5标签的简介
2012/05/28 HTML / CSS
HTML5移动端开发中的Viewport标签及相关CSS用法解析
2016/04/15 HTML / CSS
使用canvas对多图片拼合并导出图片的方法
2018/08/28 HTML / CSS
班级聚会策划书
2014/01/16 职场文书
幼儿园家长安全责任书
2014/07/22 职场文书
酒店财务部岗位职责
2015/04/14 职场文书
2016护理专业求职自荐书
2016/01/28 职场文书
python实现简单区块链结构
2021/04/25 Python