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 相关文章推荐
深入理解JavaScript系列(1) 编写高质量JavaScript代码的基本要点
Jan 15 Javascript
jquery之超简单的div显示和隐藏特效demo(分享)
Jul 09 Javascript
原生JS实现加入收藏夹的代码
Oct 24 Javascript
基于jquery自定义的漂亮单选按钮RadioButton
Nov 19 Javascript
jquery实现tr元素的上下移动示例代码
Dec 20 Javascript
jQuery实现首页顶部可伸缩广告特效代码
Apr 15 Javascript
asp.net中oracle 存储过程(图文)
Aug 12 Javascript
IScroll5 中文API参数说明和调用方法
May 21 Javascript
全面了解javascript中的错误处理机制
Jul 18 Javascript
详解Vue 多级组件透传新方法provide/inject
May 09 Javascript
使用vue-cli导入Element UI组件的方法
May 16 Javascript
jquery简易手风琴插件的封装
Oct 13 jQuery
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
phpfans留言版用到的数据操作类和分页类
2007/01/04 PHP
php错误日志简单配置方法
2016/07/11 PHP
PHP使用strrev翻转中文乱码问题的解决方法
2017/01/13 PHP
PHP区块查询实现方法分析
2018/05/12 PHP
总结PHP中初始化空数组的最佳方法
2019/02/13 PHP
Javascript开发包大全整理
2006/12/22 Javascript
理解Javascript_05_原型继承原理
2010/10/13 Javascript
用JavaScript获取DOM元素位置和尺寸大小的方法
2013/04/12 Javascript
JavaScript prototype 使用介绍
2013/08/29 Javascript
JS控制图片等比例缩放的示例代码
2013/12/24 Javascript
jQuery源码解读之removeClass()方法分析
2015/02/20 Javascript
JavaScript数据类型详解
2015/04/01 Javascript
JavaScript实现自动变换表格边框颜色
2015/05/08 Javascript
多功能jQuery树插件zTree实现权限列表简单实例
2016/07/12 Javascript
vue制作加载更多功能的正确打开方式
2016/10/12 Javascript
纯原生js实现table表格的增删
2017/01/05 Javascript
JS和canvas实现俄罗斯方块
2017/03/14 Javascript
浅谈vue方法内的方法使用this的问题
2018/09/15 Javascript
vue实现微信分享链接添加动态参数的方法
2019/04/29 Javascript
python中django框架通过正则搜索页面上email地址的方法
2015/03/21 Python
Python3中常用的处理时间和实现定时任务的方法的介绍
2015/04/07 Python
浅谈python类属性的访问、设置和删除方法
2016/07/25 Python
关于Python面向对象编程的知识点总结
2017/02/14 Python
python 实现dict转json并保存文件
2019/12/05 Python
python shapely.geometry.polygon任意两个四边形的IOU计算实例
2020/04/12 Python
python爬虫容易学吗
2020/06/02 Python
Python基于template实现字符串替换
2020/11/27 Python
英国最大的电脑零售连锁店集团:PC World
2016/10/10 全球购物
迪梵英国官方网站:Darphin英国
2017/12/06 全球购物
Skyscanner新西兰:全球领先的旅游搜索网站
2019/08/26 全球购物
铭立家具面试题
2012/12/06 面试题
委托书范本
2014/04/02 职场文书
高中家长寄语
2014/04/02 职场文书
人力资源管理专业自荐书
2014/07/07 职场文书
学生顶撞老师的检讨书
2014/09/17 职场文书
大学生自我鉴定怎么写
2019/05/07 职场文书