JavaScript中如何编写递归函数实现点分隔键转嵌套去重菜单
点分隔键递归生成去重嵌套菜单实现方案
核心问题定位
现有代码仅在一级菜单做了同名键查重,未对深层子节点执行统一的去重逻辑,本质是没有把「同层同名键复用节点」的规则递归应用到所有层级,才会出现project下多个重复type、id子项的问题。
实现思路
- 所有层级统一遵循「同层同名键仅保留一个节点,后续同路径段共享该节点的子容器」规则
- 同层节点先用对象结构存储,以路径段名为键,天然实现同层去重,避免遍历数组查重的性能损耗,最后统一转为菜单组件常用的数组格式即可
- 逐段拆分点分隔的键名,从根节点开始逐层向下遍历,不存在的节点则新建,存在则直接复用进入下一层
完整实现代码
/** * 从点分隔的平级键集合生成无重复的嵌套菜单结构 * @param {string[]} flatKeyList 从res对象中提取的所有点分隔键名数组 * @returns {Array<{label: string, children: Array}>} 标准嵌套菜单结构 */ function generateUniqueNestedMenu(flatKeyList) { // 初始化根容器,children用对象存储实现按key快速去重 const root = { children: {} } // 遍历所有平级键,逐层挂载节点 flatKeyList.forEach(fullKey => { const pathSegments = fullKey.split('.') let currentLevel = root pathSegments.forEach(seg => { // 当前层级不存在该段名的节点则新建 if (!currentLevel.children[seg]) { currentLevel.children[seg] = { label: seg, children: {} } } // 指针下移到当前节点,处理下一层路径 currentLevel = currentLevel.children[seg] }) }) // 递归将对象格式的children转为数组格式 function formatToMenuArray(node) { return Object.values(node.children).map(item => ({ ...item, // 存在子节点则递归转换,没有则返回空数组 children: Object.keys(item.children).length ? formatToMenuArray(item) : [] })) } return formatToMenuArray(root) } // 调用示例:替换为你实际从res取键名的逻辑即可 const resKeys = Object.keys(yourResponseData) const finalMenuTree = generateUniqueNestedMenu(resKeys)
效果说明
传入包含重复路径段的平级键集合(例如同时存在project.type.id、project.type.name、project.id等多个project前缀的键),最终输出结构中:
- 一级菜单的user、department、project均仅出现一次
- project节点下的type、id、name子项无重复
- type节点下的id、name子项同样自动去重,完全符合嵌套结构预期
内容的提问来源于stack exchange,提问作者su-wan Kenobi
相关产品推荐
相关产品推荐

