2011-03-30 34 views
2

我已经搜索了档案,但找不到解决方案。我试图简单地按UniqueId对实体集合进行简单分组,然后按修订号排序,并返回每个UniqueId具有最高版本号的实体。如何优化LINQ进行分组和排序

所以对于样本数据,

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

回答

0

我骗一点,并使用从morelinqMaxBy操作:

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

+0

他忽略了他想要使用的其他信息 - 这就是问题所在--LINQ缺少一个'MaxBy'运算符来获取对象而不仅仅是值。这就是为什么我使用了morelinq中的一个。 – Femaref 2011-03-31 00:07:55

0

我F你问的是有没有办法合并这两个查询,那么这里有一个简单的方式来做到这一点:

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

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