简体   繁体   English

linq重构(可能使用嵌套的group by子句)

[英]linq refactoring (possibly using nested group by clause)

I have written some linq but I am not happy with it. 我已经写了一些linq,但是我对此不满意。 I would like to refactor the two linq statements (possibly with a nested group by clause?) into just one clause. 我想将两个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)));

}

The entities involved are: 涉及的实体有:

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

A member has many results and many classifications (but only one classification per ClassificationYear). 成员具有许多结果和许多分类(但每个分类年仅一个分类)。

I need to produce a list of results for a particular year (say 2013), sorted by date. 我需要生成特定年份(例如2013)的结果列表,按日期排序。 The results need to have been grouped by the Value property of the classification class and the results are then ordered by the Value property of the result class. 需要根据分类类别的Value属性对结果进行分组,然后按结果类别的Value属性对结果进行排序。

As a tree, the result set/hierarchy might look like this: 作为一棵树,结果集/层次结构可能看起来像这样:

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)  

But ultimately, all I actually want is a flat list of the result objects: 但是最终,我真正想要的只是结果对象的平面列表:

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)

The first linq statement groups the data initially by date and then ResultList contains all the results for that date. 第一个linq语句最初按日期对数据进行分组,然后ResultList包含该日期的所有结果。

The 2nd linq statement in the loop then processes each ResultList, groups the data by classification (ignoring some classifications) and sorts those results, finally taking the top 3 results. 然后,循环中的第二个linq语句处理每个ResultList,按分类对数据进行分组(忽略某些分类)并对这些结果进行排序,最后获得前3个结果。

The loop also has (what I consider to be) a horendous .ToList(ForEach(.ToList(.ForEach()))) lambda expression, to flatten out the hierarchy into a list of result objects. 循环还具有(我认为是)可怕的.ToList(ForEach(.ToList(.ForEach())))lambda表达式,可以将层次结构展平为结果对象列表。

So, whilst this actually does work, it is pretty horrible. 因此,尽管这确实有效,但它非常可怕。 How can I merge the two linq statements and replace the lambda expression to flatten the results? 如何合并两个linq语句并替换lambda表达式以使结果变平?

ok, so the final linq that I came up with was this, including SelectMany at the end to flatten into a list: 好的,所以我想出的最后一个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();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM