C#进阶-LINQ表达式之GroupBy分组查询

简介: 本篇文章我们将演示LINQ扩展包基础语法里的GroupBy分组查询,并实现投影等实际操作中常用的类型转换手法。目前LINQ支持两种语法,我会在每个案例前先用大家熟知的SQL语句表达,再在后面用C#的两种LINQ语法分别实现。LINQ语法第一次接触难免感到陌生,最好的学习方式就是在项目中多去使用,相信会有很多感悟。

分组查询

在学习之前,我们要做一些准备工作,我们需要创建User对象和包含User对象的集合,作为后面查询和输出的数据源,参见这篇文章C#进阶之LINQ表达式总结完成准备工作。

数据源:


1、单属性分组查询全部信息

这里我们举一个最简单的例子,根据职业分组,获得每组的集合:

/* C#版本1 */IEnumerable<IGrouping<string, User>>UserGroupByOccupation=list.GroupBy(s=>s.occupation);
/* C#版本2 */IEnumerable<IGrouping<string, User>>UserGroupByOccupation=fromuinlistgroupubyu.occupationintonselectn;
/* C#版本3 *///这里的版本3是版本2的衍生版本,用自定义对象类ListGroupResult替代 IGrouping<string, User>classListGroupResult{
publicstringKey { get; set; }
publicList<User>UserList { get; set; }
}
IIEnumerable<ListGroupResult>UserGroupByOccupation=fromuinlistgroupubyu.occupationintonselectnewListGroupResult()
                  {
Key=n.Key,  //这个Key是occupationUserList=n.ToList()
                  };

根据Occupation分为四组:




/* 遍历 输出 *//*适用于C#版本1 和2*/foreach(IGrouping<string, User>uinUserGroupByOccupation)
{
Console.WriteLine(u.Key);
foreach (Useruserinu)
  {
Console.WriteLine(PrintUserObject(user));
  }
}
/*适用于C#版本3*/foreach(ListGroupResultuinUserGroupByOccupation)
{
Console.WriteLine(u.Key);
foreach (Useruserinu.UserList)
  {
Console.WriteLine(PrintUserObject(user));
  }
}
/* 输出结果 */Teacher{id=1, name=ZhangLong, age=38, gender=True, occupation=Teacher}
{id=3, name=ZhangShuai, age=38, gender=False, occupation=Teacher}
Student{id=2, name=ZhangJin, age=18, gender=False, occupation=Student}
{id=9, name=HuZiming, age=21, gender=True, occupation=Student}
{id=10, name=HuJin, age=21, gender=False, occupation=Student}
Doctor{id=4, name=LiuGuangzhi, age=38, gender=False, occupation=Doctor}
{id=5, name=LiuZiming, age=38, gender=True, occupation=Doctor}
{id=6, name=LiuShuai, age=29, gender=False, occupation=Doctor}
Builder{id=7, name=LiuJin, age=21, gender=True, occupation=Builder}
{id=8, name=JiangLong, age=38, gender=True, occupation=Builder}

2、多属性分组查询全部信息

这次,我们根据职业和性别两个属性分组,获得每组的集合:

/* C#版本1 */classListMultiGroupResult{
publicstringOccupation { get; set; }
publicboolGender { get; set; }
publicList<User>UserList { get; set; }
}
IEnumerable<ListMultiGroupResult>UserGroupByOccupationAndGender=list.GroupBy(s=>new { s.occupation, s.gender })
                .Select(g=>newListMultiGroupResult()
                {
Occupation=g.Key.occupation,
Gender=g.Key.gender,
UserList=g.ToList()
                });

这里根据Occupation和Gender分组后一共分为七组:

/* 遍历 输出 *//*适用于C#版本1*/foreach(ListMultiGroupResultuinUserGroupByOccupationAndGender)
{
Console.WriteLine(u.Occupation+"/"+u.Gender);
foreach (Useruserinu.UserList)
  {
Console.WriteLine(PrintUserObject(user));
  }
}
/* 输出结果 */Teacher/True{id=1, name=ZhangLong, age=38, gender=True, occupation=Teacher}
Student/False{id=2, name=ZhangJin, age=18, gender=False, occupation=Student}
{id=10, name=HuJin, age=21, gender=False, occupation=Student}
Teacher/False{id=3, name=ZhangShuai, age=38, gender=False, occupation=Teacher}
Doctor/False{id=4, name=LiuGuangzhi, age=38, gender=False, occupation=Doctor}
{id=6, name=LiuShuai, age=29, gender=False, occupation=Doctor}
Doctor/True{id=5, name=LiuZiming, age=38, gender=True, occupation=Doctor}
Builder/True{id=7, name=LiuJin, age=21, gender=True, occupation=Builder}
{id=8, name=JiangLong, age=38, gender=True, occupation=Builder}
Student/True{id=9, name=HuZiming, age=21, gender=True, occupation=Student}

3、分组并对各组进行数值计算

来看一个SQL中常用的场景例子:

/* SQL里的表达: 按照用户职业分组,查出每个分组的人数及各组的年龄最大值、最小值、平均值和总和 */SELECToccupation,COUNT(id),MAX(age),MIN(age),AVG(age),SUM(age) FROMUSERGROUPBYoccupation;
/* C#版本1 */classAgeGroupResult{
publicstringKey { get; set; }
publicintMaxAge { get; set; }
publicintMinAge { get; set; }
publicdoubleAvgAge { get; set; }
publicintSumAge { get; set; }
}
IEnumerable<AgeGroupResult>userList=fromuinlistgroupubyu.occupationintonselectnewAgeGroupResult()
                  {
Key=n.Key,  //这个Key是occupationMaxAge=n.Max(r=>r.age),
MinAge=n.Min(r=>r.age),
AvgAge=n.Average(r=>r.age),
SumAge=n.Sum(r=>r.age),
                  };



/* 遍历 输出 *//*适用于C#版本1*/foreach (AgeGroupResultuinuserList)
{
Console.WriteLine(PrintAgeGroupObject(u));
}
/* 输出结果 */{Key=Teacher, MaxAge=38, MinAge=38, AvgAge=38, SumAge=76}
{Key=Student, MaxAge=21, MinAge=18, AvgAge=20, SumAge=60}
{Key=Doctor, MaxAge=38, MinAge=29, AvgAge=35, SumAge=105}
{Key=Builder, MaxAge=38, MinAge=21, AvgAge=29.5, SumAge=59}



目录
相关文章
|
2月前
|
存储 机器学习/深度学习 监控
网络管理监控软件的 C# 区间树性能阈值查询算法
针对网络管理监控软件的高效区间查询需求,本文提出基于区间树的优化方案。传统线性遍历效率低,10万条数据查询超800ms,难以满足实时性要求。区间树以平衡二叉搜索树结构,结合节点最大值剪枝策略,将查询复杂度从O(N)降至O(logN+K),显著提升性能。通过C#实现,支持按指标类型分组建树、增量插入与多维度联合查询,在10万记录下查询耗时仅约2.8ms,内存占用降低35%。测试表明,该方案有效解决高负载场景下的响应延迟问题,助力管理员快速定位异常设备,提升运维效率与系统稳定性。
185 4
|
10月前
|
开发框架 安全 .NET
掌握 LINQ:通过示例解释 C# 中强大的 LINQ的集运算
通过本文的示例,我们详细介绍了C#中LINQ的强大集合运算功能。LINQ提供了一种简洁、灵活和类型安全的方式来查询和操作数据集合,从而大大提高了代码的可读性和可维护性。希望本文能帮助读者更好地掌握和应用LINQ,提高开发效率。
278 13
|
开发框架 .NET API
以C#一分钟浅谈:GraphQL 数据类型与查询
本文从C#开发者的角度介绍了GraphQL的基本概念、核心组件及其实现方法。GraphQL由Facebook开发,允许客户端精确请求所需数据,提高应用性能。文章详细讲解了如何在C#中使用`GraphQL.NET`库创建Schema、配置ASP.NET Core,并讨论了GraphQL的数据类型及常见问题与解决方案。通过本文,C#开发者可以更好地理解并应用GraphQL,构建高效、灵活的API。
296 64
|
开发框架 .NET 测试技术
C# 一分钟浅谈:GraphQL 数据类型与查询
本文介绍了GraphQL的基本概念、数据类型及查询方法,重点从C#角度探讨了GraphQL的应用。通过Hot Chocolate库的实例,展示了如何在ASP.NET Core中实现GraphQL API,包括安装、定义Schema、配置及运行项目。文中还讨论了常见问题与解决方案,旨在帮助开发者更好地理解和使用GraphQL。
181 2
|
SQL 缓存 分布式计算
C#如何处理上亿级数据的查询效率
C#如何处理上亿级数据的查询效率
300 2
|
开发框架 自然语言处理 .NET
C#一分钟浅谈:LINQ 查询表达式的使用技巧
【9月更文挑战第6天】LINQ(Language Integrated Query)是C#开发中的强大工具,使查询数据集合变得简单且接近自然语言。本文从基础入手,通过具体示例讲解LINQ查询表达式的使用技巧,包括过滤、排序和分组等操作。同时,文章还探讨了常见问题及解决方法,如性能优化、过早枚举和类型转换等,帮助开发者写出更高效、易维护的代码。
274 16
|
C#
C#一分钟浅谈:Lambda 表达式和匿名方法
本文详细介绍了C#编程中的Lambda表达式与匿名方法,两者均可用于定义无名函数,使代码更简洁易维护。文章通过基础概念讲解和示例对比,展示了各自语法特点,如Lambda表达式的`(parameters) =&gt; expression`形式及匿名方法的`delegate(parameters)`结构。并通过实例演示了两者的应用差异,强调了在使用Lambda时应注意闭包问题及其解决策略,推荐优先使用Lambda表达式以增强代码可读性。
213 8
|
开发框架 .NET C#
WPF/C#:显示分组数据的两种方式
WPF/C#:显示分组数据的两种方式
201 0
|
XML C# 数据格式
WPF/C#:如何将数据分组显示
WPF/C#:如何将数据分组显示
152 0
|
3月前
|
XML 前端开发 C#
C#编程实践:解析HTML文档并执行元素匹配
通过上述步骤,可以在C#中有效地解析HTML文档并执行元素匹配。HtmlAgilityPack提供了一个强大而灵活的工具集,可以处理各种HTML解析任务。
192 19

热门文章

最新文章