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 UI Dialog 创建友好的弹出对话框实现代码
Apr 12 Javascript
iframe异步加载实现点击左边菜单加载右边内容实例讲解
Mar 04 Javascript
使用ngView配合AngularJS应用实现动画效果的方法
Jun 19 Javascript
详谈JS中实现种子随机数及作用
Jul 19 Javascript
Angular2 (RC5) 路由与导航详解
Sep 21 Javascript
AngularJS中的DOM操作用法分析
Nov 04 Javascript
JavaScript实现弹窗效果代码分析
Mar 09 Javascript
vuex 的简单使用
Mar 22 Javascript
vue做移动端适配最佳解决方案(亲测有效)
Sep 04 Javascript
js实现无缝轮播图效果
Mar 09 Javascript
javascript设计模式 ? 解释器模式原理与用法实例分析
Apr 17 Javascript
JS出现404错误原理及解决方案
Jul 01 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
phpMyAdmin 链接表的附加功能尚未激活问题的解决方法(已测)
2012/03/27 PHP
PHP调用MsSQL Server 2012存储过程获取多结果集(包含output参数)的详解
2013/07/03 PHP
使用淘宝IP库获取用户ip地理位置
2013/10/27 PHP
php实现微信扫码支付
2017/03/26 PHP
原生JS实现Ajax通过POST方式与PHP进行交互的方法示例
2018/05/12 PHP
Yii使用EasyWechat实现小程序获取用户的openID的方法
2020/04/29 PHP
jQuery使用手册之三 CSS操作
2007/03/24 Javascript
一段多浏览器的"复制到剪贴板"javascript代码
2007/03/27 Javascript
javascript Ext JS 状态默认存储时间
2009/02/15 Javascript
jquery validate使用攻略 第四步
2010/07/01 Javascript
js调试系列 控制台命令行API使用方法
2014/06/18 Javascript
jquery阻止后续事件只执行第一个事件
2014/07/24 Javascript
ES6中的数组扩展方法
2016/08/26 Javascript
javascript基础知识之html5轮播图实例讲解(44)
2017/02/17 Javascript
JavaScript获取URL参数的方法之一
2017/03/24 Javascript
jquery获取transform里的值实现方法
2017/12/12 jQuery
vue中的mvvm模式讲解
2019/01/31 Javascript
JS实现根据详细地址获取经纬度功能示例
2019/04/16 Javascript
解决vue自定义全局消息框组件问题
2019/11/22 Javascript
[51:34]Ti4主赛事胜者组 DK vs EG 2
2014/07/19 DOTA
Python实现抓取网页并且解析的实例
2014/09/20 Python
PyQt5每天必学之布局管理
2018/04/19 Python
Python使用matplotlib绘制三维图形示例
2018/08/25 Python
Django集成CAS单点登录的方法示例
2019/06/10 Python
Python中的延迟绑定原理详解
2019/10/11 Python
django框架中间件原理与用法详解
2019/12/10 Python
jupyter notebook的安装与使用详解
2020/05/18 Python
全球销量第一生发产品:Viviscal
2017/12/21 全球购物
介绍一下Java的安全机制
2012/06/28 面试题
营销专业应届生求职信
2013/11/26 职场文书
可贵的沉默教学反思
2014/02/06 职场文书
2014年乡镇植树节活动方案
2014/02/28 职场文书
应届毕业生自荐信
2014/05/28 职场文书
小学生节水倡议书
2015/04/29 职场文书
人代会简报
2015/07/21 职场文书
通过Python把学姐照片做成拼图游戏
2022/02/15 Python