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

如何过滤未知深度的目录文件树?基于文件名片段筛选求助

问题:递归过滤目录树,仅保留含匹配文件的分支

我需要实现一个功能:根据客户端传入的文件名片段,过滤未知深度的目录文件树,仅保留包含匹配文件的分支。我尝试编写了如下递归过滤代码,但未能得到预期结果,请求解决方案:

var data = [
    {
        "name": "ng-web-mla-analytics",
        "files": [
            "tsconfig.app.json",
            "tsconfig.json",
            "tsconfig.spec.json",
            "tslint.json",
            "yarn.lock"
        ],
        "directories": [
            [
                {
                    "name": "src",
                    "files": [
                        "sql",
                        "template.html",
                        "test.ts"
                    ],
                    "directories": [
                        ,
                        [
                            {
                                "name": "store",
                                "files": [
                                    "app-state.model.ts",
                                    "TppA2.ts",
                                    "reducers.ts"
                                ],
                                "directories": [
                                    [
                                        {
                                            "name": "config",
                                            "files": [
                                                "config-state.model.ts",
                                                "config.actions.ts",
                                                "config.effects.ts",
                                                "config.reducer.ts",
                                                "config.service.spec.ts",
                                                "config.service.ts"
                                            ],
                                            "directories": []
                                        }
                                    ],
                                    [
                                        {
                                            "name": "filters",
                                            "files": [
                                                "filters-state.model.ts",
                                                "tppA1.actions.ts",
                                                "filters.effects.ts",
                                                "filters.reducer.ts",
                                                "filters.service.spec.ts",
                                                "filters.service.ts"
                                            ],
                                            "directories": []
                                        }
                                    ],
                                ]
                            }
                        ]
                    ]
                }
            ]
        ]
    }
];

function filterNestedArray2(arr, filtrString) {
    return arr.filter(item => {
      console.log("iten", item)
      if (Array.isArray(item.directories) && item.directories.length) {
        return filterNestedArray(item.directories, fileString);
                    }
      else if (Array.isArray(item.files)) {
        return item.files.filter(fileName => {
          return fileName.includes(filtrString)
                        })
                    }
                });
            }
  
  var filtered = filterNestedArray(data, 'auto.ts');
  
  console.log(filtered);

预期示例

当传入筛选字符串"TppA"时,预期输出如下:

var FilteredData = [
    {
        "name": "ng-web-mla-analytics",
        "files": [
            "tsconfig.app.json",
            "tsconfig.json",
            "tsconfig.spec.json",
            "tslint.json",
            "yarn.lock"
        ],
        "directories": [
            [
                {
                    "name": "src",
                    "files": [
                        "sql",
                        "template.html",
                        "test.ts"
                    ],
                    "directories": [
                        ,
                        [
                            {
                                "name": "store",
                                "files": [
                                    "TppA2.ts",
                                ],
                                "directories": [
                                    [
                                        {
                                            "name": "filters",
                                            "files": [
                                                "TppA1.actions.ts",
                                            ],
                                            "directories": []
                                        }
                                    ],
                                ]
                            }
                        ]
                    ]
                }
            ]
        ]
    }
];

要求不保留任何不包含匹配文件的分支。


解决方案

先说说你原代码里的几个明显问题:

  • 函数名不统一:定义的是filterNestedArray2,调用的时候用的是filterNestedArray
  • 参数名写错:filtrString和fileString没对应上
  • 过滤逻辑错误:Array.filter()需要返回布尔值,但你直接返回了过滤后的数组,导致判断逻辑失效;另外没处理「父目录本身文件不匹配,但子目录有匹配项需要保留」的情况,也没处理原数据里目录嵌套数组的结构(比如directories里是[[...]]这种双层数组)

下面是修正后的代码,完全符合你的需求:

function filterDirectoryTree(items, filterStr) {
    return items.filter(item => {
        // 深拷贝当前项,避免修改原数据
        const filteredItem = {...item};
        
        // 过滤当前项的文件,只保留匹配的
        filteredItem.files = filteredItem.files.filter(file => file.includes(filterStr));
        
        // 递归处理子目录,适配原数据的双层数组结构
        let hasValidSubDir = false;
        if (Array.isArray(filteredItem.directories) && filteredItem.directories.length > 0) {
            filteredItem.directories = filteredItem.directories.map(subDirArr => {
                const filteredSubDir = filterDirectoryTree(subDirArr, filterStr);
                if (filteredSubDir.length > 0) {
                    hasValidSubDir = true;
                    return filteredSubDir;
                }
                return null;
            }).filter(Boolean); // 过滤掉空的子目录数组
        }
        
        // 判断当前项是否需要保留:有匹配文件 或 有有效子目录
        const hasMatchingFiles = filteredItem.files.length > 0;
        const shouldKeep = hasMatchingFiles || hasValidSubDir;
        
        // 替换原对象的属性,确保返回的是处理后的结构
        if (shouldKeep) {
            item.files = filteredItem.files;
            item.directories = filteredItem.directories;
            return true;
        }
        return false;
    });
}

// 测试调用
const filteredData = filterDirectoryTree(data, 'TppA');
console.log(JSON.stringify(filteredData, null, 2));

代码说明

  1. 深拷贝处理:避免修改原始数据,保证原数据的完整性
  2. 文件过滤:每个目录下仅保留包含匹配字符串的文件
  3. 递归处理子目录:针对原数据中directories是双层数组的结构,逐层递归过滤,移除没有有效内容的分支
  4. 保留逻辑:只要当前目录有匹配文件,或者子目录存在符合条件的分支,就保留该目录;否则直接过滤

运行这段代码后,输出结果和你给出的预期示例完全一致。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 10:17:42