【问题标题】:linq refactoring (possibly using nested group by clause)linq 重构(可能使用嵌套的 group by 子句)
【发布时间】:2014-07-23 11:03:24
【问题描述】:

我写了一些 linq,但我对它不满意。我想将两个 linq 语句(可能带有嵌套的 group by 子句?)重构为一个子句。

var queryDB = from res in Results
        where res.SeasonYear == 2013
            group res by res.resultDate into g
            orderby g.Key
            select new 
            {
                ResultDate = g.Key
                , ResultList = g.OrderByDescending(r => r.Value)
            };

List<result> finalList = new List<result>();

foreach (var list in queryDB.Select(k=>k.ResultList).ToList())
{
    var query5 = from item in list
        where item.member.classifications.First(c => c.ClassificationYear == 2013).Value != "U"
        group item by item.member.classifications.First(c => c.ClassificationYear == ClassificationYear).Value into g
        orderby g.Key
        select g.ToList().OrderByDescending(r => r.Value).Take(3);

        query5.ToList().ForEach(c => c.ToList().ForEach(r => finalList.Add(r)));

}

涉及的实体有:

public class Member
{    
    public string Surname { get; set; }
    public virtual ICollection<Result> Results { get; set; }
    public virtual ICollection<Classification> Classifications { get; set; }
}
public class Result
{
    public int Value { get; set; }
    public int SeasonYear { get; set; }
    public Member member { get; set; }
}
public class Classification
{
    public string Value { get; set; }
    public int ClassificationYear { get; set; }
    public Member member { get; set; }
}

一个成员有许多结果和许多分类(但每个分类年只有一个分类)。

我需要生成一个特定年份(比如 2013 年)的结果列表,按日期排序。结果需要按分类类的 Value 属性分组,然后按结果类的 Value 属性排序。

作为一棵树,结果集/层次结构可能如下所示:

13/04/2013
    classification.Value = A
        Result (Result.Value = 44)
        Result (Result.Value = 41)
        Result (Result.Value = 40)
    classification.Value = B
        Result (Result.Value = 42)
        Result (Result.Value = 39)
        Result (Result.Value = 36)
    classification.Value = C
        Result (Result.Value = 37)
        Result (Result.Value = 35)
        Result (Result.Value = 34)      

11/05/2013
    classification.Value = A
        Result (Result.Value = 40)
        Result (Result.Value = 39)
        Result (Result.Value = 38)
    classification.Value = B
        Result (Result.Value = 39)
        Result (Result.Value = 38)
        Result (Result.Value = 37)
    classification.Value = C
        Result (Result.Value = 38)
        Result (Result.Value = 36)
        Result (Result.Value = 35)  

但最终,我真正想要的只是结果对象的平面列表:

Result (.Value= 44,.Date= 13/04/2013,.Member.Classification.Value for 2013= A)
Result (.Value= 41,.Date= 13/04/2013,.Member.Classification.Value for 2013= A)
Result (.Value= 40,.Date= 13/04/2013,.Member.Classification.Value for 2013= A)
Result (.Value= 42,.Date= 13/04/2013,.Member.Classification.Value for 2013= B)
Result (.Value= 39,.Date= 13/04/2013,.Member.Classification.Value for 2013= B)
Result (.Value= 36,.Date= 13/04/2013,.Member.Classification.Value for 2013= B)
Result (.Value= 37,.Date= 13/04/2013,.Member.Classification.Value for 2013= C)
Result (.Value= 35,.Date= 13/04/2013,.Member.Classification.Value for 2013= C)
Result (.Value= 34,.Date= 13/04/2013,.Member.Classification.Value for 2013= C)
Result (.Value= 40,.Date= 11/05/2013,.Member.Classification.Value for 2013= A)
Result (.Value= 39,.Date= 11/05/2013,.Member.Classification.Value for 2013= A)
Result (.Value= 38,.Date= 11/05/2013,.Member.Classification.Value for 2013= A)
Result (.Value= 39,.Date= 11/05/2013,.Member.Classification.Value for 2013= B)
Result (.Value= 38,.Date= 11/05/2013,.Member.Classification.Value for 2013= B)
Result (.Value= 37,.Date= 11/05/2013,.Member.Classification.Value for 2013= B)
Result (.Value= 38,.Date= 11/05/2013,.Member.Classification.Value for 2013= C)
Result (.Value= 36,.Date= 11/05/2013,.Member.Classification.Value for 2013= C)
Result (.Value= 35,.Date= 11/05/2013,.Member.Classification.Value for 2013= C)

第一个 linq 语句最初按日期对数据进行分组,然后 ResultList 包含该日期的所有结果。

循环中的第二个 linq 语句然后处理每个 ResultList,按分类对数据进行分组(忽略某些分类)并对这些结果进行排序,最后取前 3 个结果。

循环还有(我认为是)一个可怕的 .ToList(ForEach(.ToList(.ForEach()))) lambda 表达式,用于将层次结构展平为结果对象列表。

所以,虽然这确实有效,但它非常可怕。如何合并两个 linq 语句并替换 lambda 表达式以展平结果?

【问题讨论】:

标签: c# linq


【解决方案1】:

好的,所以我想出的最后一个 linq 是这样的,包括最后的 SelectMany 以展平为一个列表:

var filteredResults = 
   from res in Results
   where res.SeasonYear == 2013
   orderby res.resultDate
   group res by res.resultDate into dateGroup
   select new
   {
      ResultDate = dateGroup.Key,
      ResultList =
         from r in dateGroup
         where r.member.classifications.Single(c => c.year == 2013).Value != "U"
         group r by r.member.classifications.Single(c => c.year == 2013).Value into classifications
         orderby classifications
         select new
         {
            ClassificationGroup = classifications.Key,
            ClassificationList =                                     
               from r2 in classifications.OrderByDescending(r => r.Value).Take(3)
               select r2
         }          
   };       

   finalList = filteredResults.SelectMany(item => item.ResultList)
                              .SelectMany(inner=>inner.ClassificationList)
                              .ToList();

【讨论】:

  • 尝试在最后一行使用 SelectMany()。你不应该需要 ToList()
  • 谢谢,我修改了最后的语句以使用 SelectMany,所以现在将其扁平化为所需的列表更加整洁
猜你喜欢
  • 1970-01-01
  • 2011-01-03
  • 1970-01-01
  • 2021-02-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-26
  • 2010-10-09
相关资源
最近更新 更多