c# - 使用 Enumerable 和 Lambda 过滤文件列表并删除不需要的扩展名

标签 c# performance lambda ienumerable

我正在使用此代码

       private IEnumerable<String> FindAccessableFiles(string path, string file_pattern, bool recurse)
    {
        IEnumerable<String> emptyList = new string[0];

        if (File.Exists(path))
            return new string[] { path };

        if (!Directory.Exists(path))
            return emptyList;

        var top_directory = new DirectoryInfo(path);

        // Enumerate the files just in the top directory.
        var files = top_directory.EnumerateFiles(file_pattern);
        var filesLength = files.Count();
        var filesList = Enumerable
                  .Range(0, filesLength)
                  .Select(i =>
                  {
                      string filename = null;
                      try
                      {
                          var file = files.ElementAt(i);
                          filename = file.FullName;                              
                      }
                      catch (UnauthorizedAccessException)
                      {
                      }
                      catch (InvalidOperationException)
                      {
                          // ran out of entries
                      }
                      return filename;
                  })
                  .Where(i => null != i);

        if (!recurse)
            return filesList;

        var dirs = top_directory.EnumerateDirectories("*");
        var dirsLength = dirs.Count();
        var dirsList = Enumerable
            .Range(0, dirsLength)
            .SelectMany(i =>
            {
                string dirname = null;
                try
                {
                    var dir = dirs.ElementAt(i);
                    dirname = dir.FullName;
                    return FindAccessableFiles(dirname, file_pattern, recurse);
                }
                catch (UnauthorizedAccessException)
                {
                }
                catch (InvalidOperationException)
                {
                    // ran out of entries
                }

                return emptyList;
            });
        return Enumerable.Concat(filesList, dirsList);
    }

我在遍历包含超过 100k 个文件的文件夹时遇到了一些性能问题 - 当我枚举它们时,我忽略了所有图像。

我正在尝试弄清楚如何将它们从枚举列表中排除,这样它们就不会首先被处理,但无法弄清楚如何做到这一点。

我有一个List<String>我想排除并在代码中使用 Contains 执行此操作.

如果我将它们排除在 FindAccessableFiles 之外,我会获得性能提升吗?首先,我该怎么做?我最初的尝试是,如果文件扩展名包含在扩展名列表中,则抛出异常,但我确信这不是最好的方法。

FindAccessableFiles的目的是生成一个文件列表来规避 GetFiles() 的问题尝试访问引发权限错误的文件时引发异常。

最佳答案

部分问题在于 FindAccessableFiles返回 IEnumerable<string>每次枚举时都会重新遍历整个目录结构的实例。 SelectWhere每次遍历枚举时都会重新评估子句,因此您将多次重复这项昂贵的工作。解决此问题的一个快速解决方法是通过调用 .ToList 强制步行一次关于返回值

return Enumerable.Concat(filesList, dirsList).ToList();

请注意,这将导致此时立即遍历整个枚举。然而,它只会进行一次。

如果您仍然遇到性能问题,您应该考虑一些其他选项

  • 您提到有些图像您会忽略。在访问磁盘以获取有关它们的信息之前,我会过滤掉它们。访问磁盘比检查路径名要昂贵得多
  • 将磁盘移动到后台线程

关于c# - 使用 Enumerable 和 Lambda 过滤文件列表并删除不需要的扩展名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18360562/

相关文章:

c# - 使用 Newtonsoft Json.Net 反序列化为 IEnumerable 类

c# - 在 C# 中对字符串数组进行排序

java - 再次调用函数比将其分配给变量更好

javascript - 在 JavaScript 和 jQuery 中使用委托(delegate)事件处理程序是否存在性能缺陷?

lambda - 使用 HashMap<String, Runnable> 避免重复方法

C# 等同于 Java 的 Exception.printStackTrace()?

c# - 使用 BouncyCaSTLe 进行 OpenPGP 加密

MySQL 慢 SELECT 查询

java动态判断当前执行的类

C++14 使用捕获说明符在 lambda 函数内部递增一个值