使用Linq选择组中的最大值

Bil*_*lly 8 c# linq

哦,我发现错误是由另一部分代码引起的.案件结案.

我有2张桌子

1- userinfo

id uid name 
1 11 Billy
2 22 Paul
3 33 Joshua
Run Code Online (Sandbox Code Playgroud)

2-分数

 id uid score
 1  11  30
 2  22  40
 3  11  50
 4  11  60
 5  33  20
 6  33  70
 7  33  80
Run Code Online (Sandbox Code Playgroud)

我有一个名为ScoreUser的课程

public class ScoreUser{
public long uid{get; set;}
public string name{get;set;}
public int score{get;set;}
}
Run Code Online (Sandbox Code Playgroud)

我想使用linq查询上面两个表,获取每个用户的最大分数并将其映射到ScoreUser对象.我使用以下代码:

from s in Scores
join i in UserInfos
on s.uid equals i.uid
group uscore by new { s.uid, i.name} into g
let maxScore = g.Max(p => p.score)
select new ScoreUser
{
uid = g.Key.uid,
name = g.Key.name,
score = maxScore
 }
Run Code Online (Sandbox Code Playgroud)

但是,此代码不起作用.它产生7个物体而不是3.我该怎么办?

bru*_*nde 10

您也score应该将它作为聚合器进行分组.试试这个:

from s in Scores
join i in UserInfos on s.uid equals i.uid
group by new { s.uid, i.name } into g
select new ScoreUser
{
   uid = g.Key.uid
   name = g.Key.name,
   score = g.Max(p => p.score)
}
Run Code Online (Sandbox Code Playgroud)

(更新)

我发现你发现了问题.但是我在这里给你留下这个查询的测试:

    class UserInfo
    {
        public int Id { get; set; }
        public int UId { get; set; }
        public string Name { get; set; }
    }

    class Score
    {
        public int Id { get; set; }
        public int UId { get; set; }
        public int SScore { get; set; }
    }

    public class ScoreUser
    {
        public int uid { get; set; }
        public string name { get; set; }
        public int score { get; set; }

        public override string ToString()
        {
            return string.Format("UId:{0} Name:{1} Score:{2}", uid, name, score);
        }
    }


    static void Main(string[] args)
    {

        List<UserInfo> infos = new List<UserInfo>()
        {
            new UserInfo {Id = 1, UId = 11, Name = "Billy"},
            new UserInfo {Id = 2, UId = 22, Name = "Paul"},
            new UserInfo {Id = 3, UId = 33, Name = "Joshua"}
        };

        List<Score> scores = new List<Score>()
        {
            new Score {Id = 1, UId = 11, SScore = 30},
            new Score {Id = 2, UId = 22, SScore = 40},
            new Score {Id = 3, UId = 11, SScore = 50},
            new Score {Id = 4, UId = 11, SScore = 60},
            new Score {Id = 5, UId = 33, SScore = 20},
            new Score {Id = 6, UId = 33, SScore = 70},
            new Score {Id = 7, UId = 33, SScore = 80}
        };

        var qry = from s in scores
                  join i in infos on s.UId equals i.UId
                  group s by new { s.UId, i.Name } into g
                  select new ScoreUser
                  {
                      uid = g.Key.UId,
                      name = g.Key.Name,
                      score = g.Max(p => p.SScore)
                  };

        foreach (var su in qry)
        {
            Console.WriteLine(su);
        }
    }
Run Code Online (Sandbox Code Playgroud)

打印:

UId:11 Name:Billy Score:60
UId:22 Name:Paul Score:40
UId:33 Name:Joshua Score:80
Run Code Online (Sandbox Code Playgroud)


dus*_*88c 8

var list = records.GroupBy(p => p.Year, (key, g) => g.OrderByDescending(y => y.Month).First()).ToList();
Run Code Online (Sandbox Code Playgroud)

上面的查询将返回一个列表,其中包含按年份分组的最高月份项目。


ale*_*lex 5

为了满足某人的口味,这里提供两个使用 lambda 表达式来选择组中最大值的 LINQ

使用 lambda 表达式的 LINQ

qry = Scores.Join(UserInfos, s => s.uid, i => i.uid, (s, i) => new { s, i })
     .GroupBy(g => new { g.s.uid, g.i.name })
     .Select(g => new ScoreUser
     {
        uid = g.Key.uid,
        name = g.Key.name,
        score = g.Max(p => p.s.score)
     });
Run Code Online (Sandbox Code Playgroud)

LINQ(Lambda)使用LastOrDefault()来获取Max()值,因此这里可以消除ScoreUser()类。

var qry = Scores.Join(UserInfos, s => s.uid, i => i.uid, (s, i) => new { s, i })
         .GroupBy(g => new { g.s.uid, g.i.name })
         .Select(g => new { su = g.OrderBy(i => i.s.score) })
         .Select(x => x.su.LastOrDefault()).ToList();
Run Code Online (Sandbox Code Playgroud)

两者都获得与使用查询语法的 LINQ 相同的结果。

本文档可能对LINQ 查询语法与方法语法感兴趣 。