一、先准备要使用的类:

1、Person类:

    class Person
{
public string Name { set; get; }
public int Age { set; get; }
public string Gender { set; get; }
public override string ToString() => Name;
}

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

        List<Person> personList = new List<Person>
{
new Person
{
Name = "P1", Age = , Gender = "Male" },
new Person
{
Name = "P2", Age = , Gender = "Male",
},
new Person
{
Name = "P2", Age = ,Gender = "Female",
}
};

二、第一种用法:

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进行分组,结果为一个已分好组的集合(集合中的集合)。

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

        var groups = personList.GroupBy(p => p.Gender);
foreach (var group in groups)
{
Console.WriteLine(group.Key);
foreach(var person in group)
{
Console.WriteLine($"\t{person.Name},{person.Age}");
}
}

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

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

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

输出结果如下:

其等价的LINQ语句为:

var groups = from p in personList
group p by p.Gender;

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

三、第二种用法:

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更改如下(下划线部分):

        List<Person> personList = new List<Person>
{
new Person
{
Name = "P1", Age = , Gender = "Male" },
new Person
{
Name = "P1", Age = , Gender = "Male",
},
new Person
{
Name = "P3", Age = ,Gender = "Female",
}
};

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

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

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

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

        var groups = personList.GroupBy(p => p, new PersonEqualityComparer());
foreach (var group in groups)
{
Console.WriteLine(group.Key.ToString());
foreach(var person in group)
{
Console.WriteLine($"\t{person.Age},{person.Gender}");
}
}

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

输出结果如下:

四、第三种用法:

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

官方释义:根据指定的键选择器函数对序列中的元素进行分组,并且通过使用指定的函数对每个组中的元素进行投影。

这个比第一种用法多了一个elementSelector,第一种用法是对集合本身按照TKey分组,并将自己(TSource)添加到分组内,而当前的用法则可以选择自己想要添加到分组内的元素类型。

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

        var groups = personList.GroupBy(p => p.Gender, p=>p.Name);
foreach (var group in groups)
{
Console.WriteLine(group.Key.ToString());
foreach(var name in group)
{
Console.WriteLine($"\t{name}");
}
}

以上代码是按照p.Gender进行分组,并将p.Name作为组内的元素。

输出结果如下:

其等价的LINQ语句为:

var groups = from p in personList
group p.Name by p.Gender;

五、第四种用法:

public static IEnumerable<TResult> GroupBy<TSource, TKey, TResult>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TKey, IEnumerable<TSource>, TResult> resultSelector);

官方释义:根据指定的键选择器函数对序列中的元素进行分组,并且从每个组及其键中创建结果值。

这个跟之前的用法都不同,之前的用法都是将结果进行分组,并返回IGrouping<TKey,TSource>对象,而当前用法则是返回自己定义的类型(TResult),在返回自己定义类型之前,将会传入两个参数,一个是TKey,为分组时指定的对象,另外一个则是IEnumerable<TSource>,为分组后的内部对象集合。

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

            string GetPersonInfo(string gender, IEnumerable<Person> persons)
{
string result = $"{gender}:\t";
foreach (var p in persons)
{
result += $"{p.Name},{p.Age}\t";
}
return result;
}
var results = personList.GroupBy(p => p.Gender,(g, ps) => GetPersonInfo(g,ps));
foreach (var result in results)
{
Console.WriteLine(result);
}

GetPersonInfo为局部方法,见于C#7.0及以上。

以上代码将分组后的内容(一个是TKey,为p.Gender,另外一个是IEnumerable<TSource>,为IEnumerable<Person>)作为字符串输出,因此,将返回的类型为字符串集合。

输出结果如下:

其等价的LINQ语句为:

            var results = from p in personList
group p by p.Gender into pGroup
select GetPersonInfo(pGroup.Key, pGroup);

六、第五种用法:

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

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

与第三种用法基本相同,只是多了一个相等比较器,用于分组的依据。

使用第二种用法的personList及PersonEqualityComparer,编写客户端实验代码如下:

            var groups = personList.GroupBy(p => p, p => new { p.Age,p.Gender },new PersonEqualityComparer());
foreach (var group in groups)
{
Console.WriteLine(group.Key.ToString());
foreach (var name in group)
{
Console.WriteLine($"\t{name.Age},{name.Gender}");
}
}

以上代码的分组依据是Person,PersonEqualityComparer则是作为Person分组的比较器,每个组内为一个匿名类型集合。

输出结果如下:

七、第六种用法:

public static IEnumerable<TResult> GroupBy<TSource, TKey, TResult>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TKey, IEnumerable<TSource>, TResult> resultSelector, IEqualityComparer<TKey> comparer);

官方释义:根据指定的键选择器函数对序列中的元素进行分组,并且从每个组及其键中创建结果值。通过使用指定的比较器对键进行比较。

与第四种用法基本相同,只是多了一个相等比较器,用于分组的依据。

使用第二种用法的personList及PersonEqualityComparer,编写客户端实验代码如下:

            string GetPersonInfo(Person person, IEnumerable<Person> persons)
{
string result = $"{person.ToString()}:\t";
foreach (var p in persons)
{
result += $"{p.Age},{p.Gender}\t";
}
return result;
}
var results = personList.GroupBy(p => p, (p, ps) => GetPersonInfo(p, ps),new PersonEqualityComparer());
foreach (var result in results)
{
Console.WriteLine(result);
}

以上代码的分组依据是Person,PersonEqualityComparer则是作为Person分组的比较器,每个组内为一个Person集合,并将返回类型为string的字符串输出。

输出结果如下:

八、第七种用法:

public static IEnumerable<TResult> GroupBy<TSource, TKey, TElement, TResult>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, Func<TKey, IEnumerable<TElement>, TResult> resultSelector);

官方释义:根据指定的键选择器函数对序列中的元素进行分组,并且从每个组及其键中创建结果值。通过使用指定的函数对每个组的元素进行投影。

与第四种方法很类似,只是对分组内的元素进行选择,原有为TSource,现改为TElement。

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

            string GetPersonInfo(string gender, IEnumerable<string> names)
{
string result = $"{gender}:\t";
foreach (var name in names)
{
result += $"{name}\t";
}
return result;
}
var results = personList.GroupBy(p => p.Gender, (p=>p.Name) ,(g, ns) => GetPersonInfo(g, ns));
foreach (var result in results)
{
Console.WriteLine(result);
}

以上代码将使用Gender分组,并将分组后的信息组合成一条字符串,并输出到控制台。

输出结果如下:

九、第八种用法:

public static IEnumerable<TResult> GroupBy<TSource, TKey, TElement, TResult>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, Func<TKey, IEnumerable<TElement>, TResult> resultSelector, IEqualityComparer<TKey> comparer);

官方释义: 根据指定的键选择器函数对序列中的元素进行分组,并且从每个组及其键中创建结果值。通过使用指定的比较器对键值进行比较,并且通过使用指定的函数对每个组的元素进行投影。

与第七种用法基本相同,只是多了一个相等比较器,用于分组的依据。

使用第二种用法的personList及PersonEqualityComparer,编写客户端实验代码如下:

            var results = personList.GroupBy(p => p, (p=>new { p.Age,p.Gender}),
(p, ns) =>
{
string result = $"{p.ToString()}:\t";
foreach (var n in ns)
{
result += $"{n.Age},{p.Gender}\t";
}
return result;
},new PersonEqualityComparer());
foreach (var result in results)
{
Console.WriteLine(result);
}

以上代码将使用Person分组,使用Person比较器作为分组的依据,并将分组后的信息组合成一条字符串,并输出到控制台。

输出结果如下:

 
 
 

C# LINQ GroupBy的更多相关文章

  1. Linq GroupBy

    //Linq //var result = from p in personList // group p by p.Id // into grouped // select new { Id = g ...

  2. C# Linq GroupBy 分组过滤求和

    var delOrderData = orderLogList.Where(x => (x.OlStatus == 0 && x.OlUpId == null)).GroupBy ...

  3. 二段Linq Groupby操作

    var messages = list.GroupBy(p=>p.RefOrderNo,(k,v)=> new {OrderNo = k,SkuInfo = v}) .Select(p = ...

  4. LINQ GroupBy 查询数据赋给select

    roles.GroupBy(a => new { a.SubjectID,a.SubjectName}).Select(p => new SelectListItem() { Value ...

  5. 【随记】关于List集合用Linq GroupBy分组过后的遍历小记

    List<LeaderKaoQin> lstLeader = new List<LeaderKaoQin>();//一个List集合IGrouping<string, L ...

  6. atitit. 集合groupby 的实现(2)---自定义linq查询--java .net php

    atitit.  集合groupby 的实现(2)---自定义linq查询--java .net php 实现方式有如下 1. Linq的实现原理流程(ati总结) 1 2. groupby  与 事 ...

  7. atitit. 集合groupby 的实现(2)---自己定义linq查询--java .net php

    atitit.  集合groupby 的实现(2)---自己定义linq查询--java .net php 实现方式有例如以下 1. Linq的实现原理流程(ati总结) 1 2. groupby   ...

  8. C#解决Linq OrderBy() 失效的小技巧

    前言 前几天的一个数据列表中我用了Linq GroupBy 和OrderBy. 排序在本机正常使用,发到测试后排序死活不对,很是郁闷,总以为是程序问题.于是请教了另外一个同事.有了以下的答案. 问题原 ...

  9. EntityFramework Core技术线路(EF7已经更名为EF Core,并于2016年6月底发布)

    官方文档英文地址:https://github.com/aspnet/EntityFramework/wiki/Roadmap 历经延期和更名,新版本的实体框架终于要和大家见面了,虽然还有点害羞.请大 ...

随机推荐

  1. Beego 过滤器

    过滤器 beego 支持自定义过滤中间件,例如安全验证,强制跳转等. 过滤器函数如下所示: beego.InsertFilter(pattern string, position int, filte ...

  2. JS格式时间

    Date.prototype.format = function(format) { var o = { "M+": this.getMonth() + 1, //month &q ...

  3. centos-python3.5安装

    python版本:Python-3.5.5.tgz tar -xvf Python-3.5.5.tgz cp Python-3.5.5 /usr/local cd /usr/local/Python- ...

  4. while语句的练习一

    今天学习了while语句,自己想了一道题,试着练习,改了几次之后调试通过: 学生做题,如果全部都做对了,那么会得到老师的夸奖,如果做错了,那么每道题要罚抄十遍: namespace _999_1错题罚 ...

  5. Python If&字典 初学者笔记

    and 当俩个条件都满足时为True否为False or 任意一个条件满足时为True否为Flase not in  通常用于If语句,用来判断一个元素是否不在某个列表中 banned_user = ...

  6. sublime text3 控制台 Package Control 的安装与使用方法

    下载安装 sublime text3 直接网上搜sublime text3 下载即可,安装很简单 下一步就行,这里主要说明sublime text3 控制台 Package Control 的安装与使 ...

  7. python list comprehensions

    list comprehensions 列表解释 You now have all the knowledge necessary to begin writing list comprehensio ...

  8. 简单实现KNN(处理连续型数据)

    import numpy as np import matplotlib.pyplot as plt import time import math import collections raw_da ...

  9. commons-dbutils实现增删改查

    1.maven依赖 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="h ...

  10. 专访|高思教育创始人须佶成(上)【UncleW】

    大家好,我是校长运营圈专栏作者UncleW. 2017年9月,高思教育发布董事会公告,宣布完成5.5亿元人民币融资.成立于2009年的高思教育到今天刚刚8岁,员工人数已突破2000人,2017年共有5 ...