c # linq довольно сложная сортировка - PullRequest
0 голосов
/ 12 сентября 2018

У меня есть список объектов, которые мне нужно преобразовать в довольно сложный порядок сортировки.

Я - новичок в 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)}
]

Сложные правила сортировки: Сгруппированы по originatesFrom, внутри каждой группы, отсортированной по убыванию lastChanged, и по группам, отсортированным по возрастанию lastChanged (первого экземпляра). Наконец, те, которые имеют значение null в originatesFrom, должны быть вставлены в конец каждой группы, совпадая с их номером в originatesFrom. (да - это не будет что-то, что выходит из коробки здесь: - /)

Я пытался начать с группировки их по originatesFrom, но мне действительно нужно, чтобы они были разделены на две части, чтобы я мог отсортировать их по отдельности (я думаю?), И я не уверен, что было бы разумно использовать linq вообще, вместо того, чтобы проходить все объекты по одному, создавать несколько списков и в итоге объединять их в конце?

Хорошей частью является то, что редко будет действительно много объектов (поэтому эффективность может быть не такой уж большой проблемой). До сортировки я не буду знать, сколько будет групп и сколько объектов будет в каждой группе.

Если мне нужно лучше объяснить правила сортировки, пожалуйста, дайте мне знать!

1 Ответ

0 голосов
/ 12 сентября 2018

Предполагая, что это на самом деле 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 не замечательный?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...