@Senture

C# LINQ GroupBy, много-вложенная группировка, как правильнее делать?

Всем доброго времени суток!

У меня есть следующий список, который необходимо сгруппировать:
spoiler

var cntr = new List<Contract>()
            {
                new Contract
                {
                    ContractNumber = "1",
                    ContractorId = Guid.Parse("43ad7323-4d5d-4699-b290-a3ebbf4a028a"),
                    DateStart = new DateTime(2021, 1, 1),
                    DateEnd = new DateTime(2023, 12, 31),
                    GroupFields = new List<Guid>
                    {
                        Guid.Parse("0a67b6af-71b1-4f3a-9cdf-5195307177ef"),
                        Guid.Parse("21471679-0f69-437e-b704-43119deae1c0"),
                        Guid.Parse("66ae9449-9a3e-4f35-91d5-b90784604ef4"),
                    },
                    Id = Guid.Parse("cbabff12-18cb-44f2-a5f0-ffae42f4cb9c"),
                    IsAgreed = true,
                    Services = new List<Guid>
                    {
                        Guid.Parse("5c4d0a8a-916e-44a1-80f0-5b3b1fc31714"),
                        Guid.Parse("3bc308ec-0f74-4d59-a889-a9bff1fc3d08"),
                        Guid.Parse("342baf11-d69c-4c36-871c-d640a774daf0"),
                    },
                    IsAdditional = false,
                    ContractId = null,
                },
                new Contract
                {
                    ContractNumber = "2",
                    ContractorId = Guid.Parse("43ad7323-4d5d-46f1-b290-a3ebbf4a0281"),
                    DateStart = new DateTime(2022, 1, 1),
                    DateEnd = new DateTime(2025, 12, 31),
                    GroupFields = new List<Guid>
                    {
                        Guid.Parse("0a67b6af-71b1-4f3a-9cdf-5195307177ef"),
                        Guid.Parse("21471679-0f69-437e-b704-43119deae1c0"),
                        Guid.Parse("0a6786af-71b1-4f3a-9cdf-5195307177e1"),
                        Guid.Parse("21472679-0f69-437e-b704-43119deae1c1"),
                        Guid.Parse("66ae3449-9a3e-4f35-91d5-b90784604ef1"),
                    },
                    Id = Guid.Parse("cba4ff12-18cb-44f2-a5f0-ffae42f4cb91"),
                    IsAgreed = true,
                    Services = new List<Guid>
                    {
                        Guid.Parse("574d0a8a-916e-44a1-80f0-5b3b1fc31711"),
                        Guid.Parse("36c308ec-0f74-4d59-a889-a9bff1fc3d01"),
                        Guid.Parse("352baf11-d69c-4c36-871c-d640a774daf1"),
                    },
                    IsAdditional = false,
                    ContractId = null,
                },
                new Contract
                {
                    ContractNumber = "3",
                    ContractorId = Guid.Parse("43a17323-4d5d-4699-b290-a3ebbf4a0282"),
                    DateStart = new DateTime(2019, 1, 1),
                    DateEnd = new DateTime(2026, 12, 31),
                    GroupFields = new List<Guid>
                    {
                        Guid.Parse("0a67b6af-71b1-4f3a-9cdf-5195307177ef"),
                        Guid.Parse("21471679-0f69-437e-b704-43119deae1c0"),
                        Guid.Parse("0a67b6af-7121-4f3a-9cdf-5195307177e2"),
                        Guid.Parse("21471679-0f29-437e-b704-43119deae1c2"),
                        Guid.Parse("66ae9449-9a2e-4f35-91d5-b90784604ef2"),
                    },
                    Id = Guid.Parse("cbabff12-12cb-44f2-a5f0-ffae42f4cb92"),
                    IsAgreed = true,
                    Services = new List<Guid>
                    {
                        Guid.Parse("5c4d0a8a-9161-44a1-80f0-5b3b1fc31712"),
                        Guid.Parse("3bc308ec-0f71-4d59-a889-a9bff1fc3d02"),
                        Guid.Parse("342baf11-d691-4c36-871c-d640a774daf2"),
                    },
                    IsAdditional = false,
                    ContractId = null,
                }
            };



Правила группировки:
1. Сначала по году (т.е. если dateStart(2021) - дата окончания(2024), то получается 4 года, 2021, 2022, 2023, 2024).
2. В каждом годе должна быть группировка по отдельным GroupFields(если делать просто GroupBy, он группирует по List, а нужно по каждому отдельному Guid).
3. В каждом GroupField(Guid) группировка по ContractorId.

Я с GroupBy слабо знаком, а сроки горят. Сейчас параллельно сам ищу, гуглю, но не уверен что такую группировку можно сделать подобным образом. (Думаю может сделать разными LINQ запросами, но не понимаю еще как.)

Главная цель избежать вложенных циклов(ими то не сложно, но получается очень плохой код).

Может эта инфа полезная: этот список объектов берется из БД(некоторые поля хранятся в JSON формате).

P.S. Было бы здорово если кто подскажет где можно посмотреть примеры подобных многовложенных группировок. Или кто наткнет, что полезное почитать.

Всем спасибо!
  • Вопрос задан
  • 553 просмотра
Пригласить эксперта
Ответы на вопрос 1
@d-stream
Готовые решения - не подаю, но...
Собственно если не "сразу", то стоит ровно по шагам исходное-группировка - получившееся-группировка и так далее.

Плюс стоит ловить компромисс между читабельностью и производительностью. Чтобы не получалось как с регулярными выражениями, которые через день-два после написания уже нечитабельны... (привет от полной регулярки проверки email по rfc на пяток страниц)
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы