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))