通过布尔函数排序列表的更短方式

Svi*_*ish 11 c# sorting predicate

我有一个需要以特定方式订购的清单.我现在解决了这个问题:

var files = GetFiles()
  .OrderByDescending(x => x.Filename.StartsWith("ProjectDescription_"))
  .ThenByDescending(x => x.Filename.StartsWith("Budget_"))
  .ThenByDescending(x => x.Filename.StartsWith("CV_"))
  .ToArray();
Run Code Online (Sandbox Code Playgroud)

这些文件将合并为一个PDF文件,这里的重点是某些文件应该在开头,而其余文件应该在最后.

我想知道是否有更好的方式来编写这种"模式",因为它感觉相当糟糕,如果有更多的情况会变得更加黯然失色.


我想避免的事情,但不确定如何:多次通过列表,StartsWith每个文件的调用次数超过必要,代码多于必要的等等.

基本上我认为我想要一种OrderByPredicates聪明地满足这些标准的东西,其API的使用方式如下:

var predicates = new Func<boolean, File>[] {
  x => x.Filename == "First"
  x => x.Filename.StartsWith("Foo_"),
  x => x.Filename.StartsWith("Bar_"),
};

var files = GetFiles()
  .OrderByPredicates(predicates)
  .ThenBy(x => x.Filename);
Run Code Online (Sandbox Code Playgroud)

Seb*_*zus 7

紧凑(除了一点辅助方法)并且易于扩展:

private static readonly string[] Prefixes = {"ProjectDescription_", "Budget_", "CV_"};

public static int PrefixIndex(string name)
{
  for (int i = 0; i < Prefixes.Length; i++)
  {
    if (name.StartsWith(Prefixes[i]))
    {
      return i;
    }
  }
  return int.MaxValue;
}

// ...

var files = GetFiles().OrderBy(x => PrefixIndex(x.Name));
Run Code Online (Sandbox Code Playgroud)

  • 哦,基本上和我的答案一样 - 在我发布之前我没有看到这个.:)唯一真正的区别是我使我的非静态类. (2认同)

xan*_*tos 3

两个的幂?

var files = GetFiles()
  .Order(x => (x.Filename.StartsWith("ProjectDescription_") ? 4 : 0) + 
              (x.Filename.StartsWith("Budget_") ? 2 : 0) +
              (x.Filename.StartsWith("CV_") ? 1 : 0))
  .ToArray()
Run Code Online (Sandbox Code Playgroud)

请注意,我删除了降序并为 StartsWith 使用了反向权重。

它可能比你的还要慢,因为这个算法StartsWith每次比较总是需要 3x,而你的算法可能会在第一次“阻塞”StartsWith

请注意,我可能会做类似的事情:

string[] orders = new string[] { "ProjectDescription_", "Budget_", "CV_" };

var files = GetFiles()
    .OrderByDescending(x => x.Filename.StartsWith(orders[0]));

for (int i = 1; i < orders.Length; i++) {
    files = files.ThenByDescending(x => x.Filename.StartsWith(orders[i]));
}

var files2 = files.ToArray();
Run Code Online (Sandbox Code Playgroud)

通过这种方式,我将订单保存在字符串数组中。为了使代码更容易,我没有检查orders.Length > 0