Linq Group By Object然后选择

时间:2017-03-04 15:49:58

标签: c# linq

我希望按LeagueIdDate对记录进行分组。然后在日期订购desc,然后选择第一次出现的不同LeagueId。到目前为止,我有类似的东西,但我不知道如何在第一次出现不同的LeagueId时选择统计数据。

var stats =
    _statsRepository.FindBy(x => x.Active)
         .GroupBy(x => new { x.LeagueId, x.Date })
         .OrderByDescending(x => x.Key.Date)
         .SelectMany(x => x);

它几乎是一种获得每个联盟最新统计数据的方法。所以联赛1 = 12/02/2017,联赛2可能是02/02/17。 < ---无视这一点,可能会产生误导。

联盟中的某个日期有很多统计记录。因此,对于每个联赛的特定日期,将有多个统计数据。

Record 1:
09/01/14,
Jim,
4 Goals,
League 1

Record 2:
13/01/14,
Jack,
2 Goals,
League 1

Record 3:
13/01/14,
James,
2 Goals,
League 1

Record 4:
15/01/14,
Hannah,
2 Goals,
League 2

Record 5:
15/01/14,
Harmony,
1 Goal,
League 2

Record 6:
10/01/14,
Alision,
3 Goals,
League 2

应选择的记录是

Record 2:
13/01/14,
Jack,
2 Goals,
League 1

Record 3:
13/01/14,
James,
2 Goals,
League 1

Record 4:
15/01/14,
Hannah,
2 Goals,
League 2

Record 5:
15/01/14,
Harmony,
1 Goal,
League 2

解释:对于联赛1记录2& 3比记录1晚发生,因此它们都被选中。对于联赛2记录4&应选择5,因为它们是最新日期。

2 个答案:

答案 0 :(得分:5)

使用最新更新时,您需要按LeagueId进行分组,只需将每个分组中的所有记录Date等于分组中的最大Date

var stats = _statsRepository.FindBy(x => x.Active)
    .GroupBy(x => x.LeagueId }  
    .SelectMany(g => g.Where(x => x.Date == g.Max(y => y.Date));

获得相同结果的另一种方法是使用!Any(SQL NOT EXISTS)构造:

var baseStats = _statsRepository.FindBy(x => x.Active);
var stats = baseStats
    .Where(x => !baseStats.Any(y => y.LeagueId == x.LeagueId && y.Date > x.Date));

我假设你使用IQueryable s(即 LINQ to Objects 这些事情很重要),所以没有像Select那样的优化需要。

答案 1 :(得分:1)

你希望按联盟分组,然后在每个联赛的小组中获取最近的日期

var stats = _statsRepository.FindBy(x => x.Active)
            .GroupBy(x => new { x.LeagueId, x.Date })
            .GroupBy(g => g.Key.LeagueId)
            .Select(gg => new { LeagueId = gg.Key, Stats = gg.OrderByDescending(g => g.Key.Date).First().ToList() })
            .ToList();