如何优化 linq 的分组和排序

发布于 2024-10-27 22:18:50 字数 1111 浏览 2 评论 0原文

我已经搜索了档案,但找不到解决方案。我试图简单地按 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
            });
}

I have searched the archives but can't find a solution to this. I am trying to simply group a collection of entities by UniqueId, then sort by RevisionNumber and return the entity with the highest RevisionNumber for each UniqueId.

So for the sample data,

[UniqueId, RevisionNumber]

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

The resulting collection would return

[1, 4]
[2, 3]

Does anyone see how to combine the two statements below into a single linq query that sorts the collection, groups it, and returns the projected DTO object for only the highest revision for each unique id?

Thanks!

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

孤檠 2024-11-03 22:18:50

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

I've cheated a little and used the MaxBy operator from 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);
乖乖兔^ω^ 2024-11-03 22:18:50

我认为你可以使用以下方法来做到这一点:

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

I think you can do this using:

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

but obviously this wouldn't work if you actually wanted to get the original object rather than the Dto

网名女生简单气质 2024-11-03 22:18:50

如果您问是否有一种方法可以组合这两个查询,那么这是一种天真的方法:

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

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

If you asking is there a way to combine the two queries, then here's a naive way to do it:

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

However I would just rewrite it this way:

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

You're bound to go through the whole collection any way so you might as well sort once and get the last item within the group.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文