Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何根据预定义的序列对IEnumerable进行排序?_C#_Linq_C# 4.0_Ienumerable - Fatal编程技术网

C# 如何根据预定义的序列对IEnumerable进行排序?

C# 如何根据预定义的序列对IEnumerable进行排序?,c#,linq,c#-4.0,ienumerable,C#,Linq,C# 4.0,Ienumerable,我有一个IEnumerable 我想根据类型订购此IEnumerable。排序应基于预定义的顺序 顺序是:7,3,4,1。因此,如果集合具有这些值中的任何一个,则它们应按顺序显示,先是7,然后是3,以此类推 任何其他类型则应按升序排列 根据预定义的顺序进行订购的正确方式是什么?我是否应该将序列本身定义为枚举?创建从这些项到要排序的值(在本例中为该列表中的索引)的查找,然后您可以轻松地将每个值投影到要排序的值: var typeOrders = new int[]{7,3,4,1}; var ty

我有一个
IEnumerable

我想根据
类型订购此
IEnumerable
。排序应基于预定义的顺序

顺序是:7,3,4,1。因此,如果集合具有这些值中的任何一个,则它们应按顺序显示,先是7,然后是3,以此类推

任何其他
类型
则应按升序排列


根据预定义的顺序进行订购的正确方式是什么?我是否应该将序列本身定义为枚举?

创建从这些项到要排序的值(在本例中为该列表中的索引)的查找,然后您可以轻松地将每个值投影到要排序的值:

var typeOrders = new int[]{7,3,4,1};
var typeOrderLookup = typeOrders.Select((type,i)=>new{type,i})
    .ToDictionary(pair => pair.type, pair => pair.i);

var query = someData.OrderBy(process => typeOrderLookup[process.Type]);

如果编号顺序为
列表
,则可以按索引排序:

var ordered = processes
    .OrderByDescending(p => numbers.Contains(p.Type))
    .ThenBy(p => numbers.IndexOf(p.Type));
或者,使用LINQ的查询语法更高效、更可读:

var ordered = from proc in processes
              let index = numbers.IndexOf(proc.Type)
              orderby index == -1, index
              select proc;
index=-1
返回一个
bool
,其中
true
false
高。这就是全部的诀窍

顺便说一下,
Array
还有一个
IndexOf
方法:

let index = Array.IndexOf(numArray, proc.Type)

我从您的问题中得到的是,如果您的流程列表包含
序列=(7,3,4,1)
类型
的任何
流程,那么这些流程应该首先出现,并根据该
序列进行排序,然后,流程列表的其余部分应根据
类型
按升序排序。 我所做的基本上是创建两个列表并最终合并它们。第一个列表仅包含
序列
中的
类型
s的进程,该进程是根据序列排序的,第二个列表包含原始列表的其余部分,仅按
类型
排序

以下是您的答案和示例数据:

List<Process> processList = new List<Process>() 
{
    new Process() { Id = "1", name = "1", Type = 7},
    new Process() { Id = "2", name = "2", Type = 1},
    new Process() { Id = "3", name = "3", Type = 4},
    new Process() { Id = "4", name = "4", Type = 3},
    new Process() { Id = "5", name = "5", Type = 9},
    new Process() { Id = "6", name = "6", Type = 8},
};

List<int> sequence = new List<int>() { 7, 3, 4, 1 };
var pl = processList.Where(p => sequence.Contains(p.Type))
                                        .OrderBy(p => sequence.IndexOf(p.Type))
                    .Union(processList.Where(p => !sequence.Contains(p.Type))
                                      .OrderBy(p => p.Type));
List processList=新列表()
{
新进程(){Id=“1”,name=“1”,Type=7},
新进程(){Id=“2”,name=“2”,Type=1},
新进程(){Id=“3”,name=“3”,Type=4},
新进程(){Id=“4”,name=“4”,Type=3},
新进程(){Id=“5”,name=“5”,Type=9},
新进程(){Id=“6”,name=“6”,Type=8},
};
列表序列=新列表(){7,3,4,1};
var pl=processList.Where(p=>sequence.Contains(p.Type))
.OrderBy(p=>sequence.IndexOf(p.Type))
.Union(processList.Where(p=>!sequence.Contains(p.Type))
.OrderBy(p=>p.Type));

我们可以通过一个表达式来实现:

var order = new int[] { 7, 3, 4, 1 };
var orderedProccesses = order.Select(i => processes.FirstOrDefault(p => p.Type == i))
    .Where(p => p != null)
    .Concat(processes.Where(p => !order.Contains(p.Type)).OrderBy(p => p.Type))
    .ToArray();

首先将已定义的订单列表映射到相应的流程:

order.Select((i) => processes.FirstOrDefault(p => p.Type == i))
然后,进行健全性检查,因为不能保证订单中的每个项目都有相应的流程:

    .Where((p) => p != null)
然后添加其余的进程并按类型对它们进行排序

    .Concat(processes.Where((p) => !order.Contains(p.Type)).OrderBy((p) => p.Type))
    .Concat(processes.Where((p) => !order.Contains(p.Type)).OrderBy((p) => p.Type))