C# 自定义Linq排序

C# 自定义Linq排序,c#,linq,c#-3.0,C#,Linq,C# 3.0,我有一千多个文件夹,每个文件夹包含一个或多个具有以下名称的文件: 无序: Alison.ext Heather.ext Molly.ext Paula.ext Sam.ext Alison.ext 希瑟分机 莫莉,外线 保拉分机 Sam.ext 订购: Molly.ext Sam.ext Heather.ext Alison.ext Paula.ext 莫莉,外线 Sam.ext 希瑟分机 Alison.ext 保拉分机 我想写一个表达式来对这个列表进行如上所述的排序。您没有确切提到列表中的对象

我有一千多个文件夹,每个文件夹包含一个或多个具有以下名称的文件:

无序:

Alison.ext Heather.ext Molly.ext Paula.ext Sam.ext Alison.ext 希瑟分机 莫莉,外线 保拉分机 Sam.ext 订购:

Molly.ext Sam.ext Heather.ext Alison.ext Paula.ext 莫莉,外线 Sam.ext 希瑟分机 Alison.ext 保拉分机
我想写一个表达式来对这个列表进行如上所述的排序。

您没有确切提到列表中的对象是什么类型的,但假设它是这样的一般排列:

public class File {
  public string FileName { ... }
  public long FileSize { ... }
  /* elided */
}
然后,给定一个名为
files
的IEnumerable,您只需执行以下操作:

var result = files.OrderBy(f => f.FileName);
//使用自定义顺序创建字典
var order=“MSHAP”;
var ordedict=order.Select((c,i)=>new{Letter=c,order=i})
.ToDictionary(o=>o.字母,o=>o.顺序);
var list=新列表{“A.ext”、“H.ext”、“M.ext”、“P.ext”、“S.ext”};
//按自定义标准排序
var result=list.OrderBy(item=>orderDict[item[0]]);
不需要调用orderDict[item[0]],您可以使用一个很好的助手方法来处理边缘情况(不存在的字母、null等等)。但这就是想法。

List sortKeys=新列表{'M','s','H','A','p'};
List<char> sortKeys = new List<char> { 'M', 'S', 'H', 'A', 'P' };
sortKeys.Reverse();
List<FileInfo> files = new List<FileInfo>(6);

foreach(char sortKey in sortKeys)
{
    var topFiles = files.Where(file => file.Name.StartsWith(sortKey.ToString()));
    var remainingFiles = files.Except(topFiles);
    files = topFiles.Concat(remainingFiles).ToList();
}
sortKeys.Reverse(); 列表文件=新列表(6); foreach(sortKey中的char sortKey) { var topFiles=files.Where(file=>file.Name.StartsWith(sortKey.ToString()); var remainingFiles=files.Except(topFiles); files=topFiles.Concat(remainingFiles.ToList(); }
未经测试,我相信有更快的方法,但至少是像你所问的那样,使用linq的东西:-)

编辑:
我刚刚在你的帖子上看到了编辑,现在我不知道你到底想做什么,所以我的代码可能对你没用。

这里有一个方法,可以生成用于排序的键

public int OrderKey(string fileName)
{
  char first = fileName[0];
  int result =
     first  == 'M' ? 1 :
     first  == 'S' ? 2 :
     first  == 'H' ? 3 :
     first  == 'A' ? 4 :
     first  == 'P' ? 5 :
     6;
  return result;
}
以下是如何称呼它:

List<File> ordered = Files.OrderBy(f => OrderKey(f.FileName)).ToList();
List ordered=Files.OrderBy(f=>OrderKey(f.FileName)).ToList();

您可以将所需的订单列表存储在一个数组中

int[] iIndex = {3,2,0,4, 1};
假设str保存着你的无序列表

List<string> str = new List<string>();
str.Add("Alison.ext");
str.Add("Heather.ext");
.
.
.
List str=newlist();
str.Add(“Alison.ext”);
str.Add(“Heather.ext”);
.
.
.
将列表和相应的顺序添加到数据表中

DataTable dt = new DataTable();
                dt.Columns.Add("Order", typeof(Int32));
                dt.Columns.Add("Name");

                for (int iCount =0; iCount< str.Count ; iCount ++)
                { 
                    DataRow drow1 = dt.NewRow();
                    drow1[0] = iIndex[iCount];
                    drow1[1] = str[iCount];
                    dt.Rows.Add(drow1);

                }
                dt.AcceptChanges();
DataTable dt=newdatatable();
添加(“订单”,类型(Int32));
dt.列。添加(“名称”);
对于(int-iCount=0;iCount
Fylly订购YOUR列表以获取YOUR预期列表

 var result = from ls in dt.AsEnumerable()
                         orderby ls.Field<int>("Order")
                         select ls;      
var result=来自dt.AsEnumerable()中的ls
orderby ls.字段(“订单”)
选择ls;

@Yann Schwartz:这些只是模拟文件名,我想用的字母键是文件的第一个字母。谢谢很抱歉我以为你想要一个自定义的字母顺序(我见过一些奇怪的东西:-)@Chris:看完编辑后,我坚持我的答案:它可以按照你的要求工作(它根据第一个字母排序,按自定义顺序,先是M,然后是S,等等),你自己试试。@Yann:是的,你的答案很棒,发了一点信息后,效果非常好!谢谢这里的意图是合理的。每个排序键枚举一次集合的性能有问题。此外,考虑LINQ的延迟执行和CONTAT的交互是非常可怕的。Concat(files.Except(topFiles))Thx工作得非常好。必须对字符串代码进行排序(明显修改为使用字符串而不是字符)。必须按等级排序,而不是阿尔法。甚至捕获列表中没有的代码,将它们放在最后。
 var result = from ls in dt.AsEnumerable()
                         orderby ls.Field<int>("Order")
                         select ls;