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

Angular/TypeScript实现无限层级对象的名称过滤需求

无限层级对象数组的名称过滤解决方案

需求说明

处理无限层级的对象数组(每个对象包含id、name、children属性),实现输入监听功能按name属性过滤:

  • 返回所有名称匹配搜索词的对象
  • 保留自身名称不匹配但子孙节点名称匹配的父对象
  • 保留的父对象仅包含其下匹配的子孙节点

现有问题

当前代码仅支持父级和直接子级的过滤逻辑,无法处理深层嵌套的场景。

示例数据

原示例数组:

[原示例数组]

输入"aaa"时预期返回:

[预期结果数组]

现有代码

this.groupNameSearch.valueChanges.subscribe((value) => {
      const searchedPhrase = value.toLowerCase();

      this.groups = _.cloneDeep(this.allGroups).filter((group) => {
        const matchedGroup = group.name.toLowerCase().includes(searchedPhrase);
        group.children = group.children.filter((child) => child.name?.toLowerCase().includes(searchedPhrase));

        return matchedGroup || group.children.length;
      });
    });

解决方案

核心思路是通过递归遍历处理每一层节点,实现深层嵌套的过滤逻辑。

递归过滤函数

先实现一个递归函数,负责处理单一层级的数组,并递归处理子节点:

function filterGroups(groups: any[], searchPhrase: string): any[] {
  const lowerPhrase = searchPhrase.toLowerCase();
  return groups.reduce((result, currentGroup) => {
    // 递归处理当前节点的子节点,得到过滤后的子节点列表
    const filteredChildren = filterGroups(currentGroup.children || [], lowerPhrase);
    // 检查当前节点名称是否匹配搜索词
    const isCurrentMatch = currentGroup.name.toLowerCase().includes(lowerPhrase);

    // 若当前节点匹配,或存在匹配的子孙节点,则保留该节点
    if (isCurrentMatch || filteredChildren.length > 0) {
      result.push({
        ...currentGroup,
        children: filteredChildren // 替换为过滤后的子节点
      });
    }
    return result;
  }, []);
}

替换原有监听逻辑

将原来的订阅逻辑替换为调用递归函数:

this.groupNameSearch.valueChanges.subscribe((value) => {
  const searchedPhrase = value.toLowerCase();
  // 深拷贝原数组避免修改源数据,再传入递归函数过滤
  this.groups = filterGroups(_.cloneDeep(this.allGroups), searchedPhrase);
});

逻辑说明

  1. 递归遍历每个节点,先处理其所有子节点,确保深层的匹配节点被过滤出来
  2. 对每个节点判断是否需要保留:自身名称匹配,或者有经过滤后的子节点(说明存在匹配的子孙)
  3. 保留的节点会携带过滤后的子节点列表,只保留匹配的分支路径

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 20:30:56