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选择器 $实现原理
Dec 02 Javascript
JS 事件绑定函数代码
Apr 28 Javascript
js中设置元素class的三种方法小结
Aug 28 Javascript
jquery实现图片左右间隔滚动特效(可自动播放)
May 08 Javascript
javascript对中文按照拼音排序代码
Aug 20 Javascript
浏览器缩放检测的js代码
Sep 28 Javascript
Javascript实现图片轮播效果(二)图片序列节点的控制实现
Feb 17 Javascript
完美的js图片轮换效果
Feb 05 Javascript
JavaScript中的编码和解码函数
Feb 15 Javascript
js实现五星评价功能
Mar 08 Javascript
js使用generator函数同步执行ajax任务
Sep 05 Javascript
JavaScript监听键盘事件代码实现
Jun 03 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
不用数据库的多用户文件自由上传投票系统(1)
2006/10/09 PHP
thinkphp实现把数据库中的列的值存到下拉框中的方法
2017/01/20 PHP
PHP实现的防止跨站和xss攻击代码【来自阿里云】
2018/01/29 PHP
一个用js实现控制台控件的代码
2007/09/04 Javascript
把input初始值不写value的具体实现方法
2013/07/04 Javascript
jquery获取radio值(单选组radio)
2014/10/16 Javascript
JavaScript设计模式之外观模式介绍
2014/12/28 Javascript
angularJS 中input示例分享
2015/02/09 Javascript
javascript验证身份证号
2015/03/03 Javascript
jQuery经过一段时间自动隐藏指定元素的方法
2015/03/17 Javascript
js光标定位文本框回车表单提交问题的解决方法
2015/05/11 Javascript
JS实现获取当前URL和来源URL的方法
2016/08/24 Javascript
轻松学习Javascript闭包
2017/03/01 Javascript
js获取一组日期中最近连续的天数
2017/05/25 Javascript
微信小程序之分享页面如何返回首页的示例
2018/03/28 Javascript
JavaScript实现小球沿正弦曲线运动
2020/09/07 Javascript
bootstrap Table实现合并相同行
2019/07/19 Javascript
详解基于Vue/React项目的移动端适配方案
2019/08/23 Javascript
webpack的tree shaking的实现方法
2019/09/18 Javascript
[01:08:09]DOTA2上海特级锦标赛主赛事日 - 1 胜者组第一轮#1Liquid VS Alliance第二局
2016/03/02 DOTA
[00:12]2018DOTA2亚洲邀请赛 Somnus丶M出阵单挑
2018/04/06 DOTA
python模块之time模块(实例讲解)
2017/09/13 Python
python Web开发你要理解的WSGI & uwsgi详解
2018/08/01 Python
10行Python代码计算汽车数量的实现方法
2019/10/23 Python
python读取配置文件方式(ini、yaml、xml)
2020/04/09 Python
adidas爱尔兰官方网站:阿迪达斯运动鞋和运动服
2019/11/01 全球购物
马来西亚在线健康商店:Medipal Malaysia
2020/04/13 全球购物
报关简历自我评价怎么写
2013/09/19 职场文书
个人生活学习自我评价范文
2013/11/26 职场文书
通用求职信范文模板分享
2013/12/27 职场文书
电脑售后服务承诺书
2014/03/27 职场文书
2014业务员年终工作总结
2014/12/09 职场文书
运动会200米广播稿
2015/08/19 职场文书
节约用水广告语60条
2019/11/14 职场文书
常用的Python代码调试工具总结
2021/06/23 Python
python opencv将多个图放在一个窗口的实例详解
2022/02/28 Python