经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C# » 查看文章
[C#] LINQ之GroupBy
来源:cnblogs  作者:cnc  时间:2018/10/25 9:37:07  对本文有异议

声明:本文为www.cnc6.cn原创,转载时请注明出处,谢谢!

一、先准备要使用的类:

1、Person类:

  1. class Person
  2. {
  3. public string Name { set; get; }
  4. public int Age { set; get; }
  5. public string Gender { set; get; }
  6. public override string ToString() => Name;
  7. }

2、准备要使用的List,用于分组(GroupBy):

  1. List<Person> personList = new List<Person>
  2. {
  3. new Person
  4. {
  5. Name = "P1", Age = 18, Gender = "Male"
  6. },
  7. new Person
  8. {
  9. Name = "P2", Age = 19, Gender = "Male",
  10. },
  11. new Person
  12. {
  13. Name = "P2", Age = 17,Gender = "Female",
  14. }
  15. };

二、第一种用法:

  1. public static IEnumerable<IGrouping<TKey, TSource>> GroupBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector);

官方释义:根据指定的键选择器函数对序列中的元素进行分组。

我们要分组的集合为source,集合内每个元素的类型为TSource,这里第一个参数keySelector的类型为Func<TSource, TKey>,用于将TSource元素按照由此委托返回的类型TKey进行分组,结果为一个已分好组的集合(集合中的集合)。

编写客户端试验代码如下:

  1. var groups = personList.GroupBy(p => p.Gender);
  2. foreach (var group in groups)
  3. {
  4. Console.WriteLine(group.Key);
  5. foreach(var person in group)
  6. {
  7. Console.WriteLine($"\t{person.Name},{person.Age}");
  8. }
  9. }

以上代码指定的KeySelector是Person类的Gender属性,因此,以上会按照Gender(性别)进行分组,我们使用两个嵌套的foreach循环将分组的内容打印到控制台。

因为groups返回的类型为IEnumerable<IGouping<TKey,TSource>>,因此以上返回的类型为IEnumerable<IGouping<string,Person>>。

IGouping<string,Person>是已经分组后的集合,内部集合元素为Person,且IGouping有一个Key属性,类型为string(指的是Gender属性类型),用于分组的标识。

输出结果如下:

其等价的LINQ语句为:

  1. var groups = from p in personList
  2. group p by p.Gender into pGroup
  3. select pGroup;

以上的意思可以这样理解:从personList取出p,并对p进行分组,使用分组的依据(Key)为p.Gender,并将分组的结果存储到pGroup,并将分组的结果选择出来合并成一个集合。

 三、第二种用法:

  1. public static IEnumerable<IGrouping<TKey, TSource>> GroupBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer);

官方释义:根据指定的键选择器函数对序列中的元素进行分组,并使用指定的比较器对键进行比较。

这种比第一种方法多了一个参数,那就是一个相等比较器,目的是为了当TKey为自定义的类时,GroupBy能根据TKey指定的类根据相等比较器进行分组,

因此,自定义类如何进行分组,GroupBy是不知道的,需要自己定义自己的相等比较器。

首先,将personList更改如下(下划线部分):

  1. List<Person> personList = new List<Person>
  2. {
  3. new Person
  4. {
  5. Name = "P1", Age = 18, Gender = "Male"
  6. },
  7. new Person
  8. {
  9. Name = "P1", Age = 19, Gender = "Male",
  10. },
  11. new Person
  12. {
  13. Name = "P3", Age = 17,Gender = "Female",
  14. }
  15. };

其次,增加一个相等比较器类,用于对Person进行分组:

  1. class PersonEqualityComparer : IEqualityComparer<Person>
  2. {
  3. public bool Equals(Person x, Person y) => x.Name == y.Name;
  4. public int GetHashCode(Person obj) => obj.Name.GetHashCode();
  5. }

其中定义了如何对一个Person相等性定义,只要实现IEqualityComparer<Person>即可,这里以Name作为Person类是否相同的依据。

最后,现在我们对Person类进行分组,编写客户端实验代码如下:

  1. var groups = personList.GroupBy(p => p, new PersonEqualityComparer());
  2. foreach (var group in groups)
  3. {
  4. Console.WriteLine(group.Key.ToString());
  5. foreach(var person in group)
  6. {
  7. Console.WriteLine($"\t{person.Age},{person.Gender}");
  8. }
  9. }

以上的分组依据是Person类,并运用了自己定义的Person类相同比较器,只要Name相同,就分为一组,

输出结果如下:

第三~八种用法,待续~

 

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号