如何根据预定义的顺序订购IEnumerable?

时间:2014-01-10 21:29:09

标签: c# linq c#-4.0 ienumerable

我有IEnumerable<Process>

public class Process
{
    public string Id { get; set; }
    public string Name { get; set; }
    public int Type { get; set; }
}

我想根据IEnumerable<Process>订购此Type。排序应基于预定义的顺序。

序列是:7,3,4,1。因此,如果集合具有这些值中的任何一个,它们应该首先出现在顺序7,然后是3等等。

然后任何其他Type应该按升序排列。

根据预定义的顺序订购此产品的正确方法是什么?我应该将序列本身定义为enum

4 个答案:

答案 0 :(得分:4)

如果数字序列是List<int>,您可以按索引排序:

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)

答案 1 :(得分:1)

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

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

答案 2 :(得分:0)

我从您那里得到的问题是,如果您的流程列表包含ProcessType sequence = (7, 3, 4, 1)的任何sequence,那么这些流程应首先显示基于该Type的排序{ {1}},然后应根据Type按升序对进程列表的其余部分进行排序。 我所做的基本上是创建两个列表,最后将它们联合起来。第一个列表仅包含sequenceType的进程,该进程根据序列排序,第二个列表包含原始列表的其余部分,只按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)); 排序。

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

{{1}}

答案 3 :(得分:0)

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

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