c# linq 分组groupby
转载: https://www.cnblogs.com/cncc/p/9846390.html
一、先准备要使用的类:
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 = 18, Gender = "Male" },
new Person
{
Name = "P2", Age = 19, Gender = "Male",
},
new Person
{
Name = "P2", Age = 17,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 = 18, Gender = "Male" },
new Person
{
Name = "P1", Age = 19, Gender = "Male",
},
new Person
{
Name = "P3", Age = 17,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的更多相关文章
- Linq 中按照多个值进行分组(GroupBy)
Linq 中按照多个值进行分组(GroupBy) .GroupBy(x => new { x.Age, x.Sex }) group emp by new { emp.Age, emp.Sex ...
- Linq分组操作之GroupBy,GroupJoin扩展方法源码分析
Linq分组操作之GroupBy,GroupJoin扩展方法源码分析 一. GroupBy 解释: 根据指定的键选择器函数对序列中的元素进行分组,并且从每个组及其键中创建结果值. 查询表达式: var ...
- linq lambda GroupBy 用法
Linq 中按照多个值进行分组(GroupBy) /// <summary>要查询的对象</summary> class Employee { public int ID ...
- Linq分组功能
Linq在集合操作上很方便,很多语法都借鉴自sql,但linq的分组却与sql有一定的区别,故整理发布如下. 1. Linq分组 分组后以Key属性访问分组键值. 每一组为一个IEnumberAbl ...
- Linq Mysql GroupBy语句的问题处理
语句如下: var resumeList = db.ChannelResume.Where(model); var groupValues = resumeList.GroupBy(t => n ...
- Linq 和 Lambda 查询中按照多个值进行分组GroupBy
创建要查询的对象: class Employee { public int ID { get;set; } public string FName { get; set; } public int A ...
- 转载有个小孩跟我说LINQ(重点讲述Linq中GroupBy的原理及用法)
转载原出处: http://www.cnblogs.com/AaronYang/archive/2013/04/02/2994635.html 小孩LINQ系列导航:(一)(二)(三)(四)(五)(六 ...
- 转载Linq中GroupBy方法的使用总结
Group在SQL经常使用,通常是对一个字段或者多个字段分组,求其总和,均值等. Linq中的Groupby方法也有这种功能.具体实现看代码: 假设有如下的一个数据集: public class St ...
- Linq分组,linq方法分组
Group在SQL经常使用,通常是对一个字段或者多个字段分组,求其总和,均值等. Linq中的Groupby方法也有这种功能.具体实现看代码: 假设有如下的一个数据集: 01.public class ...
随机推荐
- react native配置ip真机测试
首先保证真机和pc 保证在同一个网络下 根据红色错误判断自己是什么情况 例如 提示无法连接远程服务,说明你的不在同一网络下 提示500 可能配置的ip不对 设置ip方法 摇晃手机 ---> De ...
- Ubuntu虚拟机共享文件夹的1234
第一 在虚拟机内添加路径 进入虚拟机软件,点开工具栏上方虚拟机,点击设置,选择选项,查看共享文件夹,点击添加,下一步 第二: 第三 点击启用此共享 点击完成 第四 查看共享的文件 在mnt里可以看到S ...
- KVM虚拟机管理(2)
一.virt-manager创建虚机 命令行需要下载下面的组件: CentOS7: 命令行界面升级为图形化界面 yum groupinstall "X Window System" ...
- 《Python编程从0到1》笔记2——表达式竟然也有副作用
在表达式的求值过程中,对状态的改变称为表达式的副作用.Python中内建的各种运算符(此处是狭义的含义,如加减乘除比较等运算符,并不包含用户自定义的运算符或函数)是没有副作用的,但各种函数调用时常带有 ...
- Kubernetes网络隔离NetworkPolicy
Kubernetes要求集群中所有pod,无论是节点内还是跨节点,都可以直接通信,或者说所有pod工作在同一跨节点网络,此网络一般是二层虚拟网络,称为pod网络.在安装引导kubernetes时,由选 ...
- 20191209 Linux就该这么学(4)
4. Vim编辑器与Shell命令脚本 Vim 编辑器中设置了三种模式-命令模式.末行模式和编辑模式. 命令模式:控制光标移动,可对文本进行复制.粘贴.删除和查找等工作. 输入模式:正常的文本录入. ...
- Flask的 sqlalchemy 操作要点
1.filter和filter_by的区别 filter,使用复杂的过滤条件,一般用两个等号进行匹配 filter,使用简单的过滤条件,一般用一个等号进行匹配 Answer.query.filter( ...
- python 并发编程 协程 greenlet模块
一 greenlet模块 不敢是yield,还是greenlet都没有实现检测io,实现遇到io切换效果 如果我们在单个线程内有20个任务,要想实现在多个任务之间切换,使用yield生成器的方式过于麻 ...
- 小记---------关于linux 定时任务crontab
linux的crontab定时任务 启动服务: service crond start 关闭服务: service crond stop 重启服务: service crond ...
- 【洛谷P1119题解】灾后重建——(floyd)
这道题告诉我,背的掉板子并不能解决一切问题,理解思想才是关键,比如不看题解,我确实想不清楚这题是弗洛伊德求最短路 (我不该自不量力的说我会弗洛伊德了我错了做人果然要谦虚) 灾后重建 题目背景 B地区在 ...