javascript将扁平的数据转为树形结构的高效率算法


Posted in Javascript onFebruary 27, 2020

当我们需要将一个一维数组转换成一个多层结构的时候,最简单但是最慢的就是多个for循环嵌套,但是这样做有一些缺点,那就是效率太低、而且有多少层就需要嵌套几个for循环,不好用。

我实现了用O(n)级算法将 一个扁平的数组即一维数组代表的菜单结构转换成一个多层级的菜单结构。

一位数组中每一个元素必须要包含以下属性:

  • 拥有一个唯一的id
  • 拥有一个parent_id, 这个id指向它父级的id

其他则为每一个元素中的一些信息,我这里是菜单,就有菜单的名称和url信息。

注:

  1. 在层级结构中,第一层的parent_id需要为0.
  2. 父节点在数组中的位置需要在子节点前,即 节点3必须排在节点3-2之前

扁平数组例:

var menu_list = [{
   id: '1',
   menu_name: '设置',
   menu_url: 'setting',
   parent_id: 0
  }, {
   id: '1-1',
   menu_name: '权限设置',
   menu_url: 'setting.permission',
   parent_id: '1'
  }, {
   id: '1-1-1',
   menu_name: '用户管理列表',
   menu_url: 'setting.permission.user_list',
   parent_id: '1-1'
  }, {
   id: '1-1-2',
   menu_name: '用户管理新增',
   menu_url: 'setting.permission.user_add',
   parent_id: '1-1'
  }, {
   id: '1-1-3',
   menu_name: '角色管理列表',
   menu_url: 'setting.permission.role_list',
   parent_id: '1-1'
  }, {
   id: '1-2',
   menu_name: '菜单设置',
   menu_url: 'setting.menu',
   parent_id: '1'
  }, {
   id: '1-2-1',
   menu_name: '菜单列表',
   menu_url: 'setting.menu.menu_list',
   parent_id: '1-2'
  }, {
   id: '1-2-2',
   menu_name: '菜单添加',
   menu_url: 'setting.menu.menu_add',
   parent_id: '1-2'
  }, {
   id: '2',
   menu_name: '订单',
   menu_url: 'order',
   parent_id: 0
  }, {
   id: '2-1',
   menu_name: '报单审核',
   menu_url: 'order.orderreview',
   parent_id: '2'
  }, {
   id: '2-2',
   menu_name: '退款管理',
   menu_url: 'order.refundmanagement',
   parent_id: '2'
  }
]

实现算法buildTree

算法思想:

先将数组中的每一个节点放到temp对象中(创建set)
即数组中有{id: '2-3', parent_id: '2',...}这样一个节点,需要将他放到temp中变成 '2-3': {id: '2-3', parent_id: '2',...}这种JSON结构

直接遍历整个temp对象,通过这句代码   temp[temp[i].parent_id].children[temp[i].id] = temp[i];   将当前子节点与父节点建立连接。是因为我们保证了父节点一定在子节点前,那么当子节点出现的时候就直接可以用temp[temp[i].parent_id]来查找到父节点这个时候先父节点的children对象中添加一个引用即可。

/**
 * 将一维的扁平数组转换为多层级对象
 * @param {[type]} list 一维数组,数组中每一个元素需包含id和parent_id两个属性 
 * @return {[type]} tree 多层级树状结构
 */
function buildTree(list){
	let temp = {};
	let tree = {};
	for(let i in list){
		temp[list[i].id] = list[i];
	}
	for(let i in temp){
		if(temp[i].parent_id) {
			if(!temp[temp[i].parent_id].children) {
				temp[temp[i].parent_id].children = new Object();
			}
			temp[temp[i].parent_id].children[temp[i].id] = temp[i];
		} else {
			tree[temp[i].id] = temp[i];
		}
	}
	return tree;
}

测试结果:

可以看到函数成功地构建了多级的树状结构

javascript将扁平的数据转为树形结构的高效率算法

这个算法的效率是极高的,比多重for循环来的好得多。

以下是测试数据,用时只需5毫秒左右:

var menu_list = [{
   id: '1',
   menu_name: '设置',
   menu_url: 'setting',
   parent_id: 0
  }, {
   id: '1-1',
   menu_name: '权限设置',
   menu_url: 'setting.permission',
   parent_id: '1'
  }, {
   id: '1-1-1',
   menu_name: '用户管理列表',
   menu_url: 'setting.permission.user_list',
   parent_id: '1-1'
  }, {
   id: '1-1-2',
   menu_name: '用户管理新增',
   menu_url: 'setting.permission.user_add',
   parent_id: '1-1'
  }, {
   id: '1-1-3',
   menu_name: '角色管理列表',
   menu_url: 'setting.permission.role_list',
   parent_id: '1-1'
  }, {
   id: '1-1-4',
   menu_name: '角色管理新增',
   menu_url: 'setting.permission.role_add',
   parent_id: '1-1'
  }, {
   id: '1-2',
   menu_name: '菜单设置',
   menu_url: 'setting.menu',
   parent_id: '1'
  }, {
   id: '1-2-1',
   menu_name: '菜单列表',
   menu_url: 'setting.menu.menu_list',
   parent_id: '1-2'
  }, {
   id: '1-2-2',
   menu_name: '菜单添加',
   menu_url: 'setting.menu.menu_add',
   parent_id: '1-2'
  }, {
   id: '2',
   menu_name: '订单',
   menu_url: 'order',
   parent_id: 0
  }, {
   id: '2-1',
   menu_name: '报单审核',
   menu_url: 'order.orderreview',
   parent_id: '2'
  }, {
   id: '2-2',
   menu_name: '退款管理',
   menu_url: 'order.refundmanagement',
   parent_id: '2'
  }, {
   id: '2-3',
   menu_name: '实物订单',
   menu_url: 'order.realorder',
   parent_id: '2'
  }, {
   id: '2-1-1',
   menu_name: '全部报单',
   menu_url: 'order.orderreview.all',
   parent_id: '2-1'
  }, {
   id: '2-2-1',
   menu_name: '所有记录',
   menu_url: 'order.refundmanagement.all',
   parent_id: '2-2'
  }, {
   id: '2-2-2',
   menu_name: '待处理',
   menu_url: 'order.refundmanagement.wait',
   parent_id: '2-2'
  }, {
   id: '2-2-3',
   menu_name: '退款原因',
   menu_url: 'order.refundmanagement.result',
   parent_id: '2-2'
  }, {
   id: '2-3-1',
   menu_name: '实物订单管理',
   menu_url: 'order.realorder.list',
   parent_id: '2-3'
  }, {
   id: '3',
   menu_name: '商品',
   menu_url: 'commodity',
   parent_id: 0
  }, {
   id: '3-1',
   menu_name: '分类管理',
   menu_url: 'commodity.classifieldmanagement',
   parent_id: '3'
  }, {
   id: '3-1-1',
   menu_name: '管理',
   menu_url: 'commodity.classifieldmanagement.management',
   parent_id: '3-1'
  }, {
   id: '3-1-2',
   menu_name: '编辑或新增',
   menu_url: 'commodity.classifieldmanagement.edit',
   parent_id: '3-1'
  }, {
   id: '3-2',
   menu_name: '品牌管理',
   menu_url: 'commodity.brandmanagement',
   parent_id: '3'
  }, {
   id: '3-2-1',
   menu_name: '管理',
   menu_url: 'commodity.brandmanagement.management',
   parent_id: '3-2'
  }, {
   id: '3-2-2',
   menu_name: '编辑或新增',
   menu_url: 'commodity.brandmanagement.edit',
   parent_id: '3-2'
  }, {
   id: '3-3',
   menu_name: '商品管理',
   menu_url: 'commodity.commoditymanagement',
   parent_id: '3'
  }, {
   id: '3-3-1',
   menu_name: '管理',
   menu_url: 'commodity.commoditymanagement.management',
   parent_id: '3-3'
  }, {
   id: '3-3-2',
   menu_name: '编辑或新增',
   menu_url: 'commodity.commoditymanagement.edit',
   parent_id: '3-3'
  }, {
   id: '3-4',
   menu_name: '类型管理',
   menu_url: 'commodity.typeManagement',
   parent_id: '3'
  }, {
   id: '3-4-1',
   menu_name: '管理',
   menu_url: 'commodity.typeManagement.management',
   parent_id: '3-4'
  }, {
   id: '3-4-2',
   menu_name: '编辑或新增',
   menu_url: 'commodity.typeManagement.edit',
   parent_id: '3-4'
  }];

这是我一个大二学生想出来的,挺开心的,因为当时看到老师用的3个for循环嵌套。嘿嘿嘿 

到此这篇关于javascript将扁平的数据转为树形结构的高效率算法的文章就介绍到这了,更多相关javascript 扁平数据转为树形结构内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
jQuery+ajax实现顶一下,踩一下效果
Jul 17 Javascript
JavaScript Scoping and Hoisting 翻译
Jul 03 Javascript
基于jquery实现点击左右按钮图片横向滚动
Apr 11 Javascript
实例讲解JS中数组Array的操作方法
May 09 Javascript
jquery中radio checked问题
Mar 16 Javascript
详述JavaScript实现继承的几种方式(推荐)
Mar 22 Javascript
带有定位当前位置的百度地图前端web api实例代码
Jun 21 Javascript
微信小程序商城项目之购物数量加减(3)
Apr 17 Javascript
微信小程序获取手机号授权用户登录功能
Nov 09 Javascript
jquery图片预览插件实现方法详解
Jul 18 jQuery
vue-video-player实现实时视频播放方式(监控设备-rtmp流)
Aug 10 Javascript
vue 中使用print.js导出pdf操作
Nov 13 Javascript
js实现无限层级树形数据结构(创新算法)
Feb 27 #Javascript
js实现树形数据转成扁平数据的方法示例
Feb 27 #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
You might like
ThinkPHP后台首页index使用frameset时的注意事项分析
2014/08/22 PHP
数组任意位置插入元素,删除特定元素的实例
2017/03/02 PHP
setInterval 和 setTimeout会产生内存溢出
2008/02/15 Javascript
jquery插件jbox使用iframe关闭问题
2009/02/09 Javascript
JavaScript中的property和attribute介绍
2011/12/26 Javascript
解析使用JS 清空File控件的路径值
2013/07/08 Javascript
鼠标移动到图片名上,显示图片的简单实例
2013/07/14 Javascript
浏览器图片选择预览、旋转、批量上传的JS代码实现
2013/12/04 Javascript
jQuery创建DOM元素实例解析
2015/01/19 Javascript
mvc中form表单提交的三种方式(推荐)
2016/08/10 Javascript
mvc 、bootstrap 结合分布式图简单实现分页
2016/10/10 Javascript
jQuery实现动态文字搜索功能
2017/01/05 Javascript
Vue.js 2.0和Cordova开发webApp环境搭建方法
2018/02/26 Javascript
vue使用xe-utils函数库的具体方法
2018/03/06 Javascript
微信小程序手动添加收货地址省市区联动
2020/05/18 Javascript
vue 自定指令生成uuid滚动监听达到tab表格吸顶效果的代码
2020/09/16 Javascript
用Python进行基础的函数式编程的教程
2015/03/31 Python
详细介绍pandas的DataFrame的append方法使用
2019/07/31 Python
django-filter和普通查询的例子
2019/08/12 Python
简述python&pytorch 随机种子的实现
2020/10/07 Python
python中pyqtgraph知识点总结
2021/01/26 Python
matplotlib之属性组合包(cycler)的使用
2021/02/24 Python
css3 条纹化和透明化表格Firefox下测试成功
2014/04/15 HTML / CSS
AmazeUI 面板的实现示例
2020/08/17 HTML / CSS
严选全球尖货,立足香港:Bonpont宝盆
2018/07/24 全球购物
波兰购物网站:MALL.PL
2019/05/01 全球购物
戛纳奢侈品商店:Jacques Loup法国
2019/11/04 全球购物
自我鉴定范文
2013/11/10 职场文书
英文自荐信格式
2013/11/28 职场文书
工程业务员岗位职责
2013/12/31 职场文书
老公爱的承诺书
2014/03/31 职场文书
初二学习计划书范文
2014/04/27 职场文书
2015年幼儿园元旦游艺活动策划书
2014/12/09 职场文书
高一地理教学工作总结
2015/08/12 职场文书
创业计划书之便利店
2019/09/05 职场文书
Java实现给Word文件添加文字水印
2022/02/15 Java/Android