javascript将扁平的数据转为树形结构 O(n)级算法

 

javascript将扁平的数据转为树形结构 O(n)级算法_huyao的博客-CSDN博客 https://blog.csdn.net/qq_37746973/article/details/78664079

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

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

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

拥有一个唯一的id
拥有一个parent_id, 这个id指向它父级的id
其他则为每一个元素中的一些信息,我这里是菜单,就有菜单的名称和url信息。

注:

在层级结构中,第一层的parent_id需要为0.
扁平数组例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
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对象中(创建map)
即数组中有{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对象中添加一个引用即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
* 将一维的扁平数组转换为多层级对象
* @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;
}

  


测试结果:

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

 

 

 

 

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

 

 

 

 

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
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循环嵌套。
————————————————

 

posted @   papering  阅读(643)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
历史上的今天:
2021-03-09 一次XSS和CSRF的组合拳进攻 (CSRF+JSON)
2021-03-09 当程序员具备了抽象思维 从码农到工匠 阿里巴巴中间件 2021-03-09
2020-03-09 LINUX动态库(.SO)搜索路径(目录)设置方法
2020-03-09 functools.singledispatchmethod(Python 3.8) | 码农网 https://www.codercto.com/a/83245.html
2019-03-09 STW
2019-03-09 进程的目标 原子 二元信号量 多元信号量 互斥量 临界区 读写锁 变量缓存到寄存器 CPU动态调度换序
2019-03-09 页式内存管理
点击右上角即可分享
微信分享提示