【问题标题】:How to sort in a linq query?如何在 linq 查询中排序?
【发布时间】:2010-11-26 19:15:13
【问题描述】:

所以我得到了一些这样的文件:

int pathLength = path.Length + 1;
var files = Directory.GetFiles ( path, "*.*", SearchOption.AllDirectories )
    .Where ( s => s.EndsWith ( ".bmp", StringComparison.OrdinalIgnoreCase ) ||
        s.EndsWith ( ".jpg", StringComparison.OrdinalIgnoreCase ) )
        .Select ( s => s.Substring ( pathLength, s.Length - pathLength ) )

    .ToList ( );

在这样排序之前:

FileComparer fileComparer = new FileComparer ( );
files.Sort ( fileComparer );

但是对于排序,我需要使用 ToList。我想知道我是否可以以同样的方式将排序添加到 Linq 并摆脱 ToList?

【问题讨论】:

  • 您也在寻找Path.GetExtension 方法。另外,您不需要 Substring 的第二个参数。看我的回答。
  • 抱歉刚刚看到。 FileComparer 实现 IComparer 如果路径有 \\ 它首先出现(因为它是一个目录),否则它是一个文件名,在后面。否则只是一个普通的字符串比较。
  • 好的,那么您的 OrderBy 子句之后也需要一个 ThenBy 子句。

标签: c# .net linq sorting io


【解决方案1】:

您正在寻找OrderBy method

var extensions = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { ".bmp", ".jpg" };
int pathLength = path.Length + 1;
var files = Directory.EnumerateFiles(path, "*.*", SearchOption.AllDirectories)
    .Where(s => extensions.Contains(Path.GetExtension(s)))
    .Select(s => s.Substring(pathLength))
    .OrderBy(s => s, new FileComparer());

你可以用

替换你的FileComparer
.OrderBy(s => !s.Contains('\\')).ThenBy(s => s)

由于false &lt; true,这将对以\\ 开头的字符串在其他字符串之前进行排序。

【讨论】:

  • 谢谢,这似乎是最好的答案。我不得不将您上次的 OrderBy 编辑更改为 s.Contains,因为 \\ 可能在任何地方。抱歉没有提到。它工作得很好。我测试的速度是差不多的。使用 FileComparer 会比使用上次编辑产生更多开销吗?
  • @Joan:不客气。我猜你的FileComparer(假设它写得很好)会快一点。但是,LINQ 调用更短。
  • 谢谢,是的,我的 FileComparer 非常简单,但速度相同,即使多 10 毫秒,您的代码也更优雅:O
【解决方案2】:

使用OrderBy 方法。

您的代码将从 -

files.Sort((x, y) => string.Compare(x.fileName, y.fileName));

到-

files.OrderBy(x => x.fileName);

更新

files.OrderBy(x => x.fileName.Contains(@"\\")).ThenBy(x => x.fileName);

【讨论】:

  • 不,不会。他没有使用那个超载。
  • 他可以去掉比较器,直接在OrderBy子句中表达比较。
  • 看他的评论,肯定不行。
【解决方案3】:
.OrderBy(f => f, new FileComparer())

(假设 FileComparer 实现了IComparer&lt;string&gt;

【讨论】:

    【解决方案4】:

    您可以做一些事情来改进您的代码:

    • 如前所述,使用 OrderBy 进行排序

    • 将您的请求写成 LINQ 表达式,而不是连续的方法调用:

      var files = (from file in Directory.GetFiles ( path, "*.*", SearchOption.AllDirectories )
                  where file.EndsWith ( ".bmp", StringComparison.OrdinalIgnoreCase ) ||
                   file.EndsWith ( ".jpg", StringComparison.OrdinalIgnoreCase )
                   orderby new FileComparer()
                   select file);
      

      上面的代码和你的一样,但是更优雅。

    • 要获取路径、扩展名、文件名...我强烈建议您使用 System.IO.Path 辅助方法,而不是执行字符串操作,如子字符串或包含!!

    • 您可以实例化一个 DirectoryInfo 并调用 GetFiles 方法,而不是使用 Directory.GetFiles:这个方法的优点是返回一个 FileInfo 数组,它直接公开扩展名、文件等属性名字...

    希望对你有帮助

    【讨论】:

    • 谢谢,查询语法和点符号之间会有速度差异吗?
    • 不,它只是语法糖。编译器将 LINQ 请求转换为使用 lambdas 的方法调用,然后最终转换为委托:最后,恕我直言,生成的 MSIL 应该是相同的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多