c#linq相当复杂的排序

时间:2018-09-12 07:55:30

标签: c# linq sorting

我有一个列表,需要按复杂的排序顺序进行按摩。

我是linq和c#/。net的完全新手(但不是其他语言的编程人员),所以我很想知道我需要朝哪个方向发展。

我的列表(简体)如下:

List[
    {nr:  1, originatesFrom: null, lastChanged: DateTime(2018,5,3)},
    {nr:  2, originatesFrom: null, lastChanged: DateTime(2018,5,3)},
    {nr:  3, originatesFrom: null, lastChanged: DateTime(2018,5,3)},
    {nr:  4, originatesFrom: 1,    lastChanged: DateTime(2018,5,1)},
    {nr:  5, originatesFrom: 2,    lastChanged: DateTime(2018,5,1)},
    {nr:  6, originatesFrom: 1,    lastChanged: DateTime(2018,5,7)},
    {nr:  7, originatesFrom: 1,    lastChanged: DateTime(2018,5,4)},
    {nr:  8, originatesFrom: 3,    lastChanged: DateTime(2018,5,13)},
    {nr:  9, originatesFrom: 1,    lastChanged: DateTime(2018,5,13)},
    {nr: 10, originatesFrom: 3,    lastChanged: DateTime(2018,5,10)},
    {nr: 11, originatesFrom: 3,    lastChanged: DateTime(2018,5,18)}
]

我需要将其按摩成这样:

List[
    {nr:  5, originatesFrom: 2,    lastChanged: DateTime(2018,5,1)},
    {nr:  2, originatesFrom: null, lastChanged: DateTime(2018,5,3)},
    {nr:  9, originatesFrom: 1,    lastChanged: DateTime(2018,5,13)},
    {nr:  6, originatesFrom: 1     lastChanged: DateTime(2018,5,7)},
    {nr:  7, originatesFrom: 1,    lastChanged: DateTime(2018,5,4)},
    {nr:  4, originatesFrom: 1,    lastChanged: DateTime(2018,5,1)},
    {nr:  1, originatesFrom: null, lastChanged: DateTime(2018,5,3)},
    {nr: 11, originatesFrom: 3,    lastChanged: DateTime(2018,5,18)},
    {nr:  8, originatesFrom: 3,    lastChanged: DateTime(2018,5,13)},
    {nr: 10, originatesFrom: 3,    lastChanged: DateTime(2018,5,10)},
    {nr:  3, originatesFrom: null, lastChanged: DateTime(2018,5,3)}
]

复杂的排序规则如下:按originsFrom分组,在按lastChanged下降顺序排序的每个组中,按(第一个实例的)lastChanged升序排序的组。最后,在originsFrom中为null的那些应该填充在与它们在originsFrom中的nr相匹配的每个组的底部。 (是的-这不是开箱即用的东西:-/)

我试图通过按originsFrom将它们分组来开始,但是我确实需要将它们拆分为appart,以便我可以对它们进行单独排序(我认为吗?),而且我不确定完全使用linq是不明智的,而不是一次遍历所有对象,而是建立多个列表并最终将它们串联起来?

好的方面是,几乎不会有太多的对象(因此效率可能不是一个大问题)。我不知道要排序多少个组,每个组中有多少个对象。

如果我需要更好地解释排序规则,请告诉我!

1 个答案:

答案 0 :(得分:4)

假设这实际上是在List<T>或类似的语言中(而不是通过IQueryable<T>,我们可能需要担心查询是否可以翻译),我相信这应该可行:

  • 按“ originatesFrom(如果非空,否则为nr”)
  • 将每个组转换为一个列表,按originatesFrom(降序)然后按lastChanged(降序)进行排序-这将在末尾保留originatesFrom为空
  • 按第一项的“ lastChanged”排序列表(升序)
  • SelectMany

这是带有示例输入数据的完整示例:

using System;
using System.Collections.Generic;
using System.Linq;

class Test
{
    static void Main()
    {
        var items = new[]
        {
             new { Number = 1, OriginatesFrom = (int?) null, LastChanged = new DateTime(2018,5,3) },
             new { Number = 2, OriginatesFrom = (int?) null, LastChanged = new DateTime(2018,5,3) },
             new { Number = 3, OriginatesFrom = (int?) null, LastChanged = new DateTime(2018,5,3) },
             new { Number = 4, OriginatesFrom = (int?) 1, LastChanged = new DateTime(2018,5,1) },
             new { Number = 5, OriginatesFrom = (int?) 2, LastChanged = new DateTime(2018,5,1) },
             new { Number = 6, OriginatesFrom = (int?) 1, LastChanged = new DateTime(2018,5,7) },
             new { Number = 7, OriginatesFrom = (int?) 1, LastChanged = new DateTime(2018,5,4) },
             new { Number = 8, OriginatesFrom = (int?) 3, LastChanged = new DateTime(2018,5,13) },
             new { Number = 9, OriginatesFrom = (int?) 1, LastChanged = new DateTime(2018,5,13) },
             new { Number = 10, OriginatesFrom = (int?) 3, LastChanged = new DateTime(2018,5,10) },
             new { Number = 11, OriginatesFrom = (int?) 3, LastChanged = new DateTime(2018,5,18 )}
        };

        var query = items
            .GroupBy(x => x.OriginatesFrom ?? x.Number)
            .Select(g => g.OrderByDescending(x => x.OriginatesFrom)
                          .ThenByDescending(x => x.LastChanged)
                          .ToList())
            .OrderBy(g => g.First().LastChanged)
            .SelectMany(g => g)
            .ToList();

        foreach (var item in query)
        {
            Console.WriteLine(item);
        }        
    }
}

输出,与您所需的订单相符:

{ Number = 5, OriginatesFrom = 2, LastChanged = 01/05/2018 00:00:00 }
{ Number = 2, OriginatesFrom = , LastChanged = 03/05/2018 00:00:00 }
{ Number = 9, OriginatesFrom = 1, LastChanged = 13/05/2018 00:00:00 }
{ Number = 6, OriginatesFrom = 1, LastChanged = 07/05/2018 00:00:00 }
{ Number = 7, OriginatesFrom = 1, LastChanged = 04/05/2018 00:00:00 }
{ Number = 4, OriginatesFrom = 1, LastChanged = 01/05/2018 00:00:00 }
{ Number = 1, OriginatesFrom = , LastChanged = 03/05/2018 00:00:00 }
{ Number = 11, OriginatesFrom = 3, LastChanged = 18/05/2018 00:00:00 }
{ Number = 8, OriginatesFrom = 3, LastChanged = 13/05/2018 00:00:00 }
{ Number = 10, OriginatesFrom = 3, LastChanged = 10/05/2018 00:00:00 }
{ Number = 3, OriginatesFrom = , LastChanged = 03/05/2018 00:00:00 }

LINQ很棒吗?