如何优化linq进行分组和排序

时间:2011-03-30 23:32:04

标签: c# linq-to-entities

我搜索了档案但找不到解决方法。我试图通过 UniqueId 简单地对实体集合进行分组,然后按 RevisionNumber 排序,并返回每个UniqueId具有最高RevisionNumber的实体。

因此,对于样本数据,

[UniqueId, RevisionNumber]

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

生成的集合将返回

[1, 4]
[2, 3]

有没有人看到如何将下面的两个语句组合成一个linq查询,该查询对集合进行排序,对其进行分组,并返回投影的DTO对象,仅针对每个唯一ID的最高版本?

谢谢!

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 :(得分:0)

我有点作弊,并使用morelinq中的MaxBy运算符:

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);

答案 1 :(得分:0)

我认为您可以使用以下方式执行此操作:

            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

,这将无效

答案 2 :(得分:0)

如果你问是否有办法将两个查询结合起来,那么这是一种天真的方式:

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
       };

您必须以任何方式浏览整个集合,以便您可以排序一次并获取组中的最后一项。