如何实现扁平化菜单对象数组按MenuId分组为嵌套子菜单结构
平级菜单转嵌套分组结构实现方法
核心逻辑是通过唯一ID做分组去重,遍历一次原始数组即可完成转换,时间复杂度O(n),性能较好。
实现步骤
- 初始化一个哈希表(推荐用
Map,也可以用普通对象),以一级菜单的MenuId作为唯一键存储分组后的一级菜单对象 - 遍历原始平级数组的每一条记录:
- 先提取当前记录里所有二级、三级菜单相关的字段,组装成子菜单对象
- 检查哈希表中是否已存在当前
MenuId对应的一级菜单:- 若不存在:提取当前记录里一级菜单的公共字段,初始化
submenus为空数组,把刚才组装的子菜单对象放进去,再存入哈希表 - 若已存在:直接把刚才组装的子菜单对象追加到对应一级菜单的
submenus数组中
- 若不存在:提取当前记录里一级菜单的公共字段,初始化
- 遍历完成后,把哈希表中存储的所有一级菜单对象转成数组,可按需根据
Orderno字段做排序后输出
可直接运行的代码示例
// 传入原始平级菜单数组,返回嵌套结构 function convertFlatMenuToNested(flatMenuData) { const menuGroupMap = new Map(); for (const item of flatMenuData) { // 提取子菜单(含三级菜单字段) const currentSubMenu = { SubMenuId: item.SubMenuId, SubMenuName: item.SubMenuName, SubMenuImage: item.SubMenuImage, SubMenuOrderno: item.SubMenuOrderno, SubSubMenuId: item.SubSubMenuId, SubSubMenuName: item.SubSubMenuName, SubSubMenuImage: item.SubSubMenuImage, SubSubMenuOrderno: item.SubSubMenuOrderno }; if (menuGroupMap.has(item.MenuId)) { // 已有同个一级菜单,直接追加子菜单 menuGroupMap.get(item.MenuId).submenus.push(currentSubMenu); } else { // 新建一级菜单分组 menuGroupMap.set(item.MenuId, { MenuId: item.MenuId, MenuName: item.MenuName, MenuImage: item.MenuImage, Orderno: item.Orderno, submenus: [currentSubMenu] }); } } // 转数组,按一级菜单排序号升序排列 const result = Array.from(menuGroupMap.values()).sort( (prev, curr) => Number(prev.Orderno) - Number(curr.Orderno) ); // 如需给每个一级菜单下的子菜单也排序,打开下面注释即可 // result.forEach(menu => { // menu.submenus.sort((prev, curr) => Number(prev.SubMenuOrderno) - Number(curr.SubMenuOrderno)) // }) return result; } // 调用示例:把原始平级数组传入即可得到目标结构 // const nestedMenu = convertFlatMenuToNested(原始平级菜单数组变量)
注意事项
你给出的期望输出示例中,GM003分组下多了一条SubMenuId: 'SM009'的「Assets Request」记录,该条记录在你提供的原始输入数组中不存在,转换逻辑不会自动生成这条数据,请确认原始数据源是否包含该条记录。
如果后续需要把三级菜单也从二级菜单中拆分嵌套成subSubMenus数组,完全复用这套分组逻辑即可,只需要在遍历子菜单时再增加一层以SubMenuId为键的分组判断。
内容的提问来源于stack exchange,提问作者Nisha Supyal
相关产品推荐
相关产品推荐

