You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多级深度菜单含指定关键词项的通用过滤方案咨询

多层嵌套菜单的通用筛选方案

问题背景

我有如下结构的多层嵌套菜单:

item1
item2
     childrenOfItem2
                    childrenOfchildren1
                    childrenOfchildren2
                    HELLOchildrenOfchildren3
     childrenOfItem2
     childrenOfItem2
HELLOitem3
item4
     childrenOfItem4
     HELLOchildrenOfItem4
item5
     childrenOfItem5

需要筛选出所有标题包含"HELLO"的菜单项,当前采用多层嵌套循环的方式实现,但如果菜单新增层级,该方案就会失效,求更通用的实现方式。

当前实现的问题

以下是当前的实现代码,核心问题是硬编码了三层循环,只能处理固定三级的菜单结构,一旦菜单新增层级,代码就无法覆盖:

const matchName = (item, word) =>
  item?.title?.toLowerCase()?.includes(word?.toLowerCase());

const filter = (word = "", arr = []) => {
  const listOfItems = [];
  arr.forEach((item) => {
    if (matchName(item, word)) {
      listOfItems.push(item);
    } else if (item?.children?.length > 0) {
      const newSubItem = [];
      item.children.forEach((subItem) => {
        if (matchName(subItem, word)) {
          newSubItem.push(subItem);
        } else if (subItem?.children?.length > 0) {
          const newSubSubItems = [];
          subItem.children.forEach((subsubItem) => {
            if (matchName(subsubItem, word)) {
              newSubSubItems.push(subsubItem);
            }
          });
          if (newSubSubItems?.length > 0) {
            newSubItem.push({ ...subItem, children: newSubSubItems });
          }
        }
      });
      if (newSubItem?.length > 0) {
        listOfItems.push({ ...item, children: newSubItem });
      }
    }
  });
  return listOfItems;
};

通用解决方案:递归实现

使用递归函数可以处理任意层级的嵌套菜单,不管菜单新增多少层,代码都不需要修改。核心思路是:遍历当前层级的每个项,若当前项匹配则直接保留;若不匹配但有子菜单,就递归处理子菜单,若子菜单有匹配结果,则保留当前项并替换为筛选后的子菜单。

完整递归实现代码

const matchName = (item, word) =>
  item?.title?.toLowerCase()?.includes(word?.toLowerCase());

const filterMenu = (word = "", arr = []) => {
  const result = [];
  arr.forEach(item => {
    // 复制当前项,避免修改原始数据
    const currentItem = { ...item };
    
    // 当前项匹配关键词,直接加入结果
    if (matchName(currentItem, word)) {
      result.push(currentItem);
    } else {
      // 递归处理子菜单
      if (currentItem.children?.length > 0) {
        const filteredChildren = filterMenu(word, currentItem.children);
        // 子菜单有匹配结果时,保留当前项并更新子菜单
        if (filteredChildren.length > 0) {
          currentItem.children = filteredChildren;
          result.push(currentItem);
        }
      }
    }
  });
  return result;
};

测试示例

基于你提供的示例数据,修改部分项的标题加入"HELLO"进行测试:

// 带测试数据的菜单
const testList = [
  {
    id: "41",
    title: "sample",
    children: [
      {
        id: "42",
        title: "sample",
        children: [
          { id: "43", title: "sample", children: [] },
          { id: "44", title: "sample", children: [] },
          { id: "45", title: "HELLOsample", children: [] },
        ],
      },
      {
        id: "46",
        title: "sample",
        children: [
          { id: "47", title: "sample", children: [] },
          { id: "48", title: "sample", children: [] },
        ],
      },
    ],
  },
  {
    id: "29",
    title: "sample",
    children: [
      { id: "30", title: "sample", children: [] },
      { id: "49", title: "HELLOsample", children: [] },
      { id: "31", title: "sample", children: [] },
    ],
  },
];

// 调用筛选函数
const filteredResult = filterMenu("HELLO", testList);
console.log(filteredResult);

输出结果说明

最终结果会包含:

  • 第一个父级项(id:41),其子项仅保留id:42的项,而id:42的子项仅保留匹配的id:45项
  • 第二个父级项(id:29),其子项仅保留匹配的id:49项

不管后续菜单新增多少层级,递归函数都会自动遍历所有子节点,无需修改代码。

内容的提问来源于stack exchange,提问作者Ewejnog

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 14:30:42