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循环嵌套。
————————————————
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 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 页式内存管理