3

我有一个需要按相当复杂的排序顺序按摩的对象列表。

我是 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 分组开始,但我真的需要将它们分开,以便我可以单独对它们进行排序(我认为?),我不确定使用 linq 是否明智,而不是去一次一个地遍历所有对象,建立几个列表并最终将它们连接起来?

好的部分是很少会有很多对象(所以效率可能不是那么大的问题)。在对将有多少组进行排序之前,我不会知道每个组中有多少对象。

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

4

1 回答 1

4

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

  • originatesFrom按“如果非空;nr否则”分组
  • 将每个组转换为一个列表,按originatesFrom(降序)然后按(降序)排序 - 这将在最后lastChanged保持 nulloriginatesFrom
  • 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 不是很棒吗?

于 2018-09-12T08:03:49.770 回答