【问题标题】:How to optimize linq for grouping and sorting如何优化 linq 进行分组和排序
【发布时间】:2011-03-30 23:32:04
【问题描述】:

我已经搜索了档案,但找不到解决方案。我试图简单地按 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 查询,对集合进行排序、分组,并仅返回每个唯一 ID 的最高修订版本的投影 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
            });
}

【问题讨论】:

    标签: c# linq-to-entities


    【解决方案1】:

    我作弊了一点,使用了 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);
    

    【讨论】:

      【解决方案2】:

      我认为你可以这样做:

                  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,这显然是行不通的

      【讨论】:

      • 他省略了他想使用的其他信息——这就是问题所在——LINQ 缺少一个MaxBy 运算符来获取对象而不仅仅是值。这就是我使用 morelinq 的原因。
      【解决方案3】:

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

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

      您一定会以任何方式浏览整个集合,因此您不妨排序一次并获取组中的最后一项。

      【讨论】:

        猜你喜欢
        • 2016-10-27
        • 1970-01-01
        • 2021-06-30
        • 2017-11-29
        • 1970-01-01
        • 1970-01-01
        • 2012-04-22
        • 2013-06-21
        • 1970-01-01
        相关资源
        最近更新 更多