Как оптимизировать linq для группировки и сортировки - PullRequest
2 голосов
/ 31 марта 2011

Я искал в архивах, но не могу найти решение этой проблемы.Я пытаюсь просто сгруппировать коллекцию сущностей по UniqueId , затем отсортировать по RevisionNumber и вернуть сущность с наибольшим RevisionNumber для каждого UniqueId.

Так что дляпример данных,

[UniqueId, RevisionNumber]

[1, 1]
[1, 2]
[1, 3]
[1, 4]
[2, 1]
[2, 2]
[2, 3]

Результирующая коллекция вернет

[1, 4]
[2, 3]

Кто-нибудь видит, как объединить два приведенных ниже оператора в один запрос linq, который сортирует коллекцию, группирует ее ивозвращает спроецированный объект DTO только для самой высокой ревизии для каждого уникального идентификатора?

Спасибо!

private static IEnumerable<RevisionDto> ExtractHighestRevisions(IEnumerable<RevisionEntity> revisions)
{
    var groupedRevisions = (from r in revisions
                orderby r.RevisionNumber descending
                group r by r.UniqueId
                    into grp
                    select grp.OrderByDescending(g => g.RevisionNumber).FirstOrDefault());

    return (from r in groupedRevisions 
            orderby r.RevisionNumber
            select new RevisionDto
            {
               // other properties omitted for clarity
               UniqueId = r.UniqueId,
               RevisionNumber = r.RevisionNumber
            });
}

Ответы [ 3 ]

0 голосов
/ 31 марта 2011

Я думаю, вы можете сделать это, используя:

            var q = from r in revisions
                    group r by r.UniqueId into grouped
                    select new ReveisonDto
                    {
                        UniqueId = grouped.Key,
                        RevisionNumber = grouped.Max(x => x.RevisionNumber)
                    };

, но, очевидно, это не сработает, если вы на самом деле хотите получить оригинальный объект, а не Dto

0 голосов
/ 31 марта 2011

Если вы спрашиваете, есть ли способ объединить два запроса, то вот наивный способ сделать это:

return from r in revisions
       orderby r.RevisionNumber descending
       group r by r.UniqueId
           into grp
       select grp.OrderByDescending(g => g.RevisionNumber).FirstOrDefault() into groupedRevisions
       from r in groupedRevisions 
       orderby r.RevisionNumber
       select new RevisionDto
       {
           // other properties omitted for clarity
           UniqueId = r.UniqueId,
           RevisionNumber = r.RevisionNumber
       };

Однако я бы просто переписал это так:

return from r in revisions
       orderby r.RevisionNumber
       group r by r.UniqueId
           into grp
       let r = grp.Last()
       select new RevisionDto
       {
           // other properties omitted for clarity
           UniqueId = r.UniqueId,
           RevisionNumber = r.RevisionNumber
       };

Вы обязательно должны пройти всю коллекцию любым способом, так что вы можете также отсортировать один раз и получить последний элемент в группе.

0 голосов
/ 31 марта 2011

Я немного обманул и использовал оператор MaxBy из morelinq :

return revisions
        .GroupBy(r => r.UniqueID)
        .SelectMany(g => g.MaxBy(r => r.RevisionNumber))
        .Select(r => 
          new RevisionDto 
              {
                 UniqueId = r.UniqueId,
                 RevisionNumber = r.RevisionNumber
              })
        .OrderBy(r => r.RevisionNumber);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...