zoukankan      html  css  js  c++  java
  • 转载Linq中GroupBy方法的使用总结

    Group在SQL经常使用,通常是对一个字段或者多个字段分组,求其总和,均值等。

    Linq中的Groupby方法也有这种功能。具体实现看代码:

    假设有如下的一个数据集:

    1. public class StudentScore 
    2.     { 
    3.         public int ID { setget; } 
    4.         public string Name { setget; } 
    5.         public string Course { setget; } 
    6.         public int Score { setget; } 
    7.         public string Term { setget; } 
    8.     } 
    9. List<StudentScore> lst = new List<StudentScore>() { 
    10.                 new StudentScore(){ID=1,Name="张三",Term="第一学期",Course="Math",Score=80}, 
    11.                 new StudentScore(){ID=1,Name="张三",Term="第一学期",Course="Chinese",Score=90}, 
    12.                 new StudentScore(){ID=1,Name="张三",Term="第一学期",Course="English",Score=70}, 
    13.                 new StudentScore(){ID=2,Name="李四",Term="第一学期",Course="Math",Score=60}, 
    14.                 new StudentScore(){ID=2,Name="李四",Term="第一学期",Course="Chinese",Score=70}, 
    15.                 new StudentScore(){ID=2,Name="李四",Term="第一学期",Course="English",Score=30}, 
    16.                 new StudentScore(){ID=3,Name="王五",Term="第一学期",Course="Math",Score=100}, 
    17.                 new StudentScore(){ID=3,Name="王五",Term="第一学期",Course="Chinese",Score=80}, 
    18.                 new StudentScore(){ID=3,Name="王五",Term="第一学期",Course="English",Score=80}, 
    19.                 new StudentScore(){ID=4,Name="赵六",Term="第一学期",Course="Math",Score=90}, 
    20.                 new StudentScore(){ID=4,Name="赵六",Term="第一学期",Course="Chinese",Score=80}, 
    21.                 new StudentScore(){ID=4,Name="赵六",Term="第一学期",Course="English",Score=70}, 
    22.                 new StudentScore(){ID=1,Name="张三",Term="第二学期",Course="Math",Score=100}, 
    23.                 new StudentScore(){ID=1,Name="张三",Term="第二学期",Course="Chinese",Score=80}, 
    24.                 new StudentScore(){ID=1,Name="张三",Term="第二学期",Course="English",Score=70}, 
    25.                 new StudentScore(){ID=2,Name="李四",Term="第二学期",Course="Math",Score=90}, 
    26.                 new StudentScore(){ID=2,Name="李四",Term="第二学期",Course="Chinese",Score=50}, 
    27.                 new StudentScore(){ID=2,Name="李四",Term="第二学期",Course="English",Score=80}, 
    28.                 new StudentScore(){ID=3,Name="王五",Term="第二学期",Course="Math",Score=90}, 
    29.                 new StudentScore(){ID=3,Name="王五",Term="第二学期",Course="Chinese",Score=70}, 
    30.                 new StudentScore(){ID=3,Name="王五",Term="第二学期",Course="English",Score=80}, 
    31.                 new StudentScore(){ID=4,Name="赵六",Term="第二学期",Course="Math",Score=70}, 
    32.                 new StudentScore(){ID=4,Name="赵六",Term="第二学期",Course="Chinese",Score=60}, 
    33.                 new StudentScore(){ID=4,Name="赵六",Term="第二学期",Course="English",Score=70}, 
    34.             }; 

    可以把这个数据集想象成数据库中的一个二维表格。

    示例一

    通常我们会把分组后得到的数据放到匿名对象中,因为分组后的数据的列不一定和原始二维表格的一致。当然要按照原有数据的格式存放也是可以的,只需select的时候采用相应的类型即可。

    第一种写法很简单,只是根据下面分组。 

    1. //分组,根据姓名,统计Sum的分数,统计结果放在匿名对象中。两种写法。 
    2. //第一种写法 
    3. Console.WriteLine("---------第一种写法"); 
    4. var studentSumScore_1 = (from l in lst 
    5.                          group l by l.Name into grouped 
    6.                          orderby grouped.Sum(m => m.Score) 
    7.                          select new { Name = grouped.Key, Scores = grouped.Sum(m => m.Score) }).ToList(); 
    8. foreach (var l in studentSumScore_1) 
    9.     Console.WriteLine("{0}:总分{1}", l.Name, l.Scores); 
    10. 第二种写法和第一种其实是等价的。 
    11. //第二种写法 
    12. Console.WriteLine("---------第二种写法"); 
    13. var studentSumScore_2 = lst.GroupBy(m => m.Name) 
    14.     .Select(k => new { Name = k.Key, Scores = k.Sum(l => l.Score) }) 
    15.     .OrderBy(m => m.Scores).ToList(); 
    16. foreach (var l in studentSumScore_2) 
    17.     Console.WriteLine("{0}:总分{1}", l.Name, l.Scores); 

    示例二

    当分组的字段是多个的时候,通常把这多个字段合并成一个匿名对象,然后group by这个匿名对象。

    注意:groupby后将数据放到grouped这个变量中,grouped 其实是IGrouping<TKey, TElement>类型的,IGrouping<out TKey, out TElement>继承了IEnumerable<TElement>,并且多了一个属性就是Key,这个Key就是当初分组的关键字,即那些值都相同的字段,此处就是该匿名对象。可以在后续的代码中取得这个Key,便于我们编程。

    orderby多个字段的时候,在SQL中是用逗号分割多个字段,在Linq中就直接多写几个orderby。

    1. //分组,根据2个条件学期和课程,统计各科均分,统计结果放在匿名对象中。两种写法。 
    2. Console.WriteLine("---------第一种写法"); 
    3. var TermAvgScore_1 = (from l in lst 
    4.                       group l by new { Term = l.Term, Course = l.Course } into grouped 
    5.                       orderby grouped.Average(m => m.Score) ascending 
    6.                       orderby grouped.Key.Term descending 
    7.                       select new { Term = grouped.Key.Term, Course = grouped.Key.Course, Scores = grouped.Average(m => m.Score) }).ToList(); 
    8. foreach (var l in TermAvgScore_1) 
    9.     Console.WriteLine("学期:{0},课程{1},均分{2}", l.Term, l.Course, l.Scores); 
    10. Console.WriteLine("---------第二种写法"); 
    11. var TermAvgScore_2 = lst.GroupBy(m => new { Term = m.Term, Course = m.Course }) 
    12.     .Select(k => new { Term = k.Key.Term, Course = k.Key.Course, Scores = k.Average(m => m.Score) }) 
    13.     .OrderBy(l => l.Scores).OrderByDescending(l => l.Term); 
    14. foreach (var l in TermAvgScore_2) 
    15.     Console.WriteLine("学期:{0},课程{1},均分{2}", l.Term, l.Course, l.Scores); 

    示例三

    Linq中没有SQL中的Having语句,因此是采用where语句对Group后的结果过滤。 

    1. //分组,带有Having的查询,查询均分>80的学生 
    2. Console.WriteLine("---------第一种写法"); 
    3. var AvgScoreGreater80_1 = (from l in lst 
    4.                   group l by new { Name = l.Name, Term = l.Term } into grouped 
    5.                   where grouped.Average(m => m.Score)>=80 
    6.                   orderby grouped.Average(m => m.Score) descending 
    7.                   select new { Name = grouped.Key.Name, Term = grouped.Key.Term, Scores = grouped.Average(m => m.Score) }).ToList(); 
    8. foreach (var l in AvgScoreGreater80_1) 
    9.     Console.WriteLine("姓名:{0},学期{1},均分{2}", l.Name, l.Term, l.Scores); 
    10. Console.WriteLine("---------第二种写法"); 
    11. //此写法看起来较为复杂,第一个Groupby,由于是要对多个字段分组的,因此构建一个匿名对象,
    12. 对这个匿名对象分组,分组得到的其实是一个IEnumberable<IGrouping<匿名类型,StudentScore>>这样一个类型。
    13. Where方法接受,和返回的都同样是IEnumberable<IGrouping<匿名类型,StudentScore>>类型,
    14. 其中Where方法签名Func委托的类型也就成了Func<IGrouping<匿名类型,StudentScore>,bool>,
    15. 之前说到,IGrouping<out TKey, out TElement>继承了IEnumerable<TElement>,
    16. 因此这种类型可以有Average,Sum等方法。 
    17. var AvgScoreGreater80_2 = lst.GroupBy(l => new { Name = l.Name, Term = l.Term }) 
    18.     .Where(m => m.Average(x => x.Score) >= 80) 
    19.     .OrderByDescending(l=>l.Average(x=>x.Score)) 
    20.     .Select(l => new { Name = l.Key.Name, Term = l.Key.Term, Scores = l.Average(m => m.Score) }).ToList(); 
    21. foreach (var l in AvgScoreGreater80_2) 
    22.     Console.WriteLine("姓名:{0},学期{1},均分{2}", l.Name, l.Term, l.Scores); 
    23. }  

  • 相关阅读:
    poj 1328 Radar Installation (贪心)
    hdu 2037 今年暑假不AC (贪心)
    poj 2965 The Pilots Brothers' refrigerator (dfs)
    poj 1753 Flip Game (dfs)
    hdu 2838 Cow Sorting (树状数组)
    hdu 1058 Humble Numbers (DP)
    hdu 1069 Monkey and Banana (DP)
    hdu 1087 Super Jumping! Jumping! Jumping! (DP)
    必须知道的.NET FrameWork
    使用记事本+CSC编译程序
  • 原文地址:https://www.cnblogs.com/wphl-27/p/3480167.html
Copyright © 2011-2022 走看看