【.NET Core】Linq查询运算符(三)

简介: 笔记

一、概述


查询运算符是组成Linq模式的方法。这些方法中的大多数都作用于序列;其中序列指其类型实现IEnumberable<T>接口或IQueryable<T>接口的对象。标准查询运算符提供包括筛选、投影、集合、排序等查询功能。

查询运算符包含两组,一组作用于类型IEnumberable<T>的对象,另一组作用于类型IQueryable<T>的对象。

《Linq查询运算符(一)》详细介绍了筛选数据、投影运算、设置运算 、数据排序、限定符运算及数据分区等

《Linq查询运算符(二)》详细介绍了生成运算、相等运算、元素运算、转换数据类型等,

本文将继续介绍Linq运算符串联运算、聚合运算、联接运算及数据分组。


二、串联运算


2.1 Enumerable.Concat

连接两个序列。

public static System.Collections.Generic.IEnumerable<TSource> Concat<TSource> (this System.Collections.Generic.IEnumerable<TSource> first, System.Collections.Generic.IEnumerable<TSource> second);

参数类型

TSource:输入序列中的元素的类型。


参数

first IEnumerable

要连接的第一个序列

second IEnumerable

要与第一个序列连接的序列


返回

一个包含两个输入序列的连接元素的IEnumerable

Person[] parameters = new Person[]
{
   new Person() { Id = 1, Code = "052", Name = "正一郎" },
   new Person() { Id = 2, Code = "028", Name = "正贰郎" },
   new Person() { Id = 3, Code = "020", Name = "正叁郎" }
};
Person[] parameters1 = new Person[]{
   new Person() { Id = 1, Code = "030", Name = "次一郎" },
   new Person() { Id = 2, Code = "031", Name = "次二郎" },
   new Person() { Id = 3, Code = "032", Name = "次三郎" }
};
var three= parameters.Select(p => p.Name).Concat(parameters1.Select(p=>p.Name));
foreach (var person in three) 
{
   Console.WriteLine(person);
}

输出结果

正一郎
正次郎
誠三郎
次一郎
次贰郎
次叁郎


三、聚合运算


聚合运算从值的集合中计算出单个值。


3.1 Aggregate

对序列应用累加器函数。 将指定的种子值用作累加器的初始值,并使用指定的函数选择结果值。

public static TResult Aggregate<TSource,TAccumulate,TResult> (this System.Linq.IQueryable<TSource> source, TAccumulate seed, System.Linq.Expressions.Expression<Func<TAccumulate,TSource,TAccumulate>> func, System.Linq.Expressions.Expression<Func<TAccumulate,TResult>> selector);


类型参数

TSource source的元素类型。

TAccumulate 累加器值的类型。

TResult 结果值的类型。


参数

source 要对其进行聚合的序列

seed TAccumulate累加器的初始值

func Expression<Func<TAccumulate,TSource,TAccumulate>>

要对每个元素调用的累加器函数

selector Expression<Func<TAccumulate,TResult>>

将累加器的最终值转换为结果值的函数。


返回

TResult

已转换的累加器最终值。

string[] fruits = { "apple", "mango", "orange", "passionfruit", "grape" };
string result=  fruits.AsEnumerable().Aggregate("", (current, next) => current + " " + next+"   ");
Console.WriteLine(result);

运行结果

apple    mango    orange    passionfruit    grape


3.2 Average

计算可以为 null 的数值序列的平均值,这些值可通过对输入序列的每个元素调用转换函数获得。

定义

public static T Average (this System.Collections.Generic.IEnumerable<T> source);

T为数值类型

string[] numbers = { "100", "98", "50","2" };
double average = numbers.Average(num => long.Parse(num));
Console.WriteLine("The average is {0}.", average);

运行结果

The average is 62.5.


3.3 Count

返回指定的序列中满足条件的元素数量。

定义


public static int Count<TSource> (this System.Collections.Generic.IEnumerable<TSource> source);
string[] fruits = { "apple", "mango", "orange", "passionfruit", "grape" };
int fruitCount = fruits.Count();
Console.WriteLine($"水果的种类:{fruitCount}.");
int fruitCount2 = fruits.Count(e=>e.IndexOf('m')==0);
Console.WriteLine($"水果的种类:{fruitCount2}.");

运行结果

水果的种类:5.
水果的种类:1.


3.4 LongCount

返回序列中的元素数量的Int64

定义

public static long LongCount<TSource> (this System.Collections.Generic.IEnumerable<TSource> source, Func<TSource,bool> predicate);
string[] fruits = { "apple", "mango", "orange", "passionfruit", "grape" };
long fruitCount = fruits.LongCount();
Console.WriteLine($"水果的种类:{fruitCount}.");
long fruitCount2 = fruits.LongCount(e=>e.IndexOf('m')==0);
Console.WriteLine($"水果的种类:{fruitCount2}.");

运行结果

水果的种类:5.
水果的种类:1.


3.5 Max 或 MaxBy

确定集合中的最大值

定义

public static TSource? Max<TSource> (this System.Collections.Generic.IEnumerable<TSource> source, System.Collections.Generic.IComparer<TSource>? comparer);
string[] fruits = { "apple", "mango", "orange", "passionfruit", "grape" };
string[] numbers = { "100", "98", "50","2" };
int maxInt = numbers.Max(x => int.Parse(x));
Console.WriteLine(maxInt);
int maxLength = fruits.Max(x => x.Length);
Console.WriteLine(maxLength);

运行结果

100
12


3.6 Min 或 MinBy

确定集合中的最下值

Min<TSource>(IEnumerable<TSource>, Func<TSource,Double>)
string[] fruits = { "apple", "mango", "orange", "passionfruit", "grape" };
string[] numbers = { "100", "98", "50","2" };
int minInt = numbers.Min(x => int.Parse(x));
Console.WriteLine(minInt);
int minLength = fruits.Min(x => x.Length);
Console.WriteLine(minLength);

运行结果

2
5


3.7 Sum

对集合中的值求和。如果 source 不包含任何元素,则此方法返回零。

定义

Sum<TSource>(IEnumerable<TSource>, Func<TSource,Single>)Sum<TSource>(IEnumerable<TSource>, Func<TSource,Single>)


四、聚合运算


联接两个数据源就是将一个数据源中的对象与另一个数据源中具有相同公共属性的对象相关联。


当查询所有面向的数据源相互之间具有无法直接领会的关系时,Join就成为一项重要的运算。在面向对象的编程中,这可能意味着建模对象之间进行关联。Linq框架中提供的join方法包括Join和GroupJoin。这些方法执行同等联接。既根据2个数据源的键是否相等来匹配这2个数据源的联接。


定义测试测试类Product

class Product
{
    public string? Name { get; set; }
    public int CategoryId { get; set; }
}

定义测试测试类Category

class Category
{
    public int Id { get; set; }
    public string? CategoryName { get; set; }
}


4.1 Join

根据键选择器函数Join两个序列并提取值对。

表达式语法

Join … in … on … equals …

List<Product> products = new List<Product>
{
     new Product { Name = "Cola", CategoryId = 0 },
     new Product { Name = "Tea", CategoryId = 0 },
     new Product { Name = "Apple", CategoryId = 1 },
     new Product { Name = "Kiwi", CategoryId = 1 },
     new Product { Name = "Carrot", CategoryId = 2 } 
};
List<Category> categories = new List<Category> {
     new Category { Id = 0, CategoryName = "Beverage" },
     new Category { Id = 1, CategoryName = "Fruit" },
     new Category { Id = 2, CategoryName = "Vegetable" }
};
var query = from product in products
            join category in categories on product.CategoryId equals category.Id
            select new { product.Name,product.CategoryId, category.CategoryName };
foreach (var item in query)
{
     Console.WriteLine($"{item.Name} - {item.CategoryName}");
}

运行结果

Cola - Beverage
Tea - Beverage
Apple - Fruit
Kiwi - Fruit
Carrot - Vegetable


4.1 GroupJoin

根据键选择器函数Join两个序列,并对每个元素的结果匹配项进行分组。

表达式语法

join … in … on … equals …

List<Product> products = new List<Product>
{
       new Product { Name = "Cola", CategoryId = 0 },
       new Product { Name = "Tea", CategoryId = 0 },
       new Product { Name = "Apple", CategoryId = 1 },
       new Product { Name = "Kiwi", CategoryId = 1 },
       new Product { Name = "Carrot", CategoryId = 2 } 
};
List<Category> categories = new List<Category> {
     new Category { Id = 0, CategoryName = "Beverage" },
     new Category { Id = 1, CategoryName = "Fruit" },
     new Category { Id = 2, CategoryName = "Vegetable" }
};
var productGroups = from category in categories
                    join product in products on category.Id equals product.CategoryId
                    into productGroup select productGroup;
foreach (IEnumerable<Product> productGroup in productGroups)
{
    Console.WriteLine("Group");
    foreach (Product product in productGroup)
    {
       Console.WriteLine($"{product.Name,8}");
    }
}


五、数据分组


分组是指将数据分到不同的组,使每组中的元素拥有公共的属性。


5.1 GroupBy

对共享通用属性的元素进行分组,每组由一个IGrouping<TKey,TElement>对象表示

查询表达式语法

groupby


List<Product> products = new List<Product>
{
       new Product { Name = "Cola", CategoryId = 0 },
       new Product { Name = "Tea", CategoryId = 0 },
       new Product { Name = "Apple", CategoryId = 1 },
       new Product { Name = "Kiwi", CategoryId = 1 },
       new Product { Name = "Carrot", CategoryId = 2 } 
};
List<Category> categories = new List<Category> {
     new Category { Id = 0, CategoryName = "Beverage" },
     new Category { Id = 1, CategoryName = "Fruit" },
     new Category { Id = 2, CategoryName = "Vegetable" }
};
var proGroups = products.GroupBy(e => e.CategoryId);
foreach (var gp in proGroups)
{
     Console.WriteLine($"GroupByValue:{gp.Key}");
     foreach (var g in gp)
     {
         Console.WriteLine($"GroupValue:{g.Name}");
     }
}
Console.WriteLine($"=.=.=.=.=.=.=.=.=.=.=.=.=.=.=.=.=.=.=.=.=.=.=.=.=.=.=.=");
var goups = from product in products group product by product.CategoryId into productGroup select productGroup;
foreach (var ps in goups) 
{
   Console.WriteLine($"GroupByKey:{ps.Key}");
   foreach (var grp in ps) 
   {
       Console.WriteLine($"GroupValue:{grp.Name}");
   }
}


5.2 ToLookup

根据指定的键选择器和元素选择器函数,从IEnumerable生成一个泛型Lookup<TKey,TElement>。

语法:

public static System.Linq.ILookup<TKey,TElement> ToLookup<TSource,TKey,TElement> (this System.Collections.Generic.IEnumerable<TSource> source, Func<TSource,TKey> keySelector, Func<TSource,TElement> elementSelector);

类型参数

TSource source的元素类型。

TKey keySelector返回的键的类型。

TElement elementSelector返回的值的类型。

ILookup<int, string> lookupProduct = products .ToLookup(p => p.CategoryId,p => p.Name);
foreach (var vproduct in lookupProduct) 
{
     Console.WriteLine($"Key:{vproduct.Key}");
     foreach (var pro in vproduct) 
     {
          Console.WriteLine($"Value:{pro}");
      }
}


六、总结


LINQ采用表达式声明性的查询语法编写,这样可以用最少的代码进行对数据结构操作。Linq也提供丰富的操作函数,在实际的使用中根据不同应用常见选择恰当的方法。

目录
相关文章
|
1月前
|
消息中间件 前端开发 小程序
一个基于.NET Core构建的简单、跨平台、模块化的商城系统
今天大姚给大家分享一个基于.NET Core构建的简单、跨平台、模块化、完全开源免费(MIT License)的商城系统:Module Shop。
|
1月前
|
算法 C# 数据库
【干货】一份10万字免费的C#/.NET/.NET Core面试宝典
C#/.NET/.NET Core相关技术常见面试题汇总,不仅仅为了面试而学习,更多的是查漏补缺、扩充知识面和大家共同学习进步。该知识库主要由自己平时学习实践总结、网上优秀文章资料收集(这一部分会标注来源)和社区小伙伴提供三部分组成。该份基础面试宝典完全免费,发布两年来收获了广大.NET小伙伴的好评,我会持续更新和改进,欢迎关注我的公众号【追逐时光者】第一时间获取最新更新的面试题内容。
|
1月前
|
数据可视化 网络协议 C#
C#/.NET/.NET Core优秀项目和框架2024年3月简报
公众号每月定期推广和分享的C#/.NET/.NET Core优秀项目和框架(每周至少会推荐两个优秀的项目和框架当然节假日除外),公众号推文中有项目和框架的介绍、功能特点、使用方式以及部分功能截图等(打不开或者打开GitHub很慢的同学可以优先查看公众号推文,文末一定会附带项目和框架源码地址)。注意:排名不分先后,都是十分优秀的开源项目和框架,每周定期更新分享(欢迎关注公众号:追逐时光者,第一时间获取每周精选分享资讯🔔)。
|
2月前
|
开发框架 JavaScript .NET
asp.net中条件查询+分页
asp.net中条件查询+分页
19 1
|
2月前
|
SQL 数据库 C#
C# .NET面试系列十一:数据库SQL查询(附建表语句)
#### 第1题 用一条 SQL 语句 查询出每门课都大于80 分的学生姓名 建表语句: ```sql create table tableA ( name varchar(10), kecheng varchar(10), fenshu int(11) ) DEFAULT CHARSET = 'utf8'; ``` 插入数据 ```sql insert into tableA values ('张三', '语文', 81); insert into tableA values ('张三', '数学', 75); insert into tableA values ('李四',
75 2
C# .NET面试系列十一:数据库SQL查询(附建表语句)
|
19天前
|
开发框架 前端开发 JavaScript
JavaScript云LIS系统源码ASP.NET CORE 3.1 MVC + SQLserver + Redis医院实验室信息系统源码 医院云LIS系统源码
实验室信息系统(Laboratory Information System,缩写LIS)是一类用来处理实验室过程信息的软件,云LIS系统围绕临床,云LIS系统将与云HIS系统建立起高度的业务整合,以体现“以病人为中心”的设计理念,优化就诊流程,方便患者就医。
22 0
|
1月前
|
Linux API iOS开发
.net core 优势
.NET Core 的优势:跨平台兼容(Windows, macOS, Linux)及容器支持,高性能,支持并行版本控制,丰富的新增API,以及开源。
27 4
|
1月前
|
开发框架 人工智能 .NET
C#/.NET/.NET Core拾遗补漏合集(持续更新)
在这个快速发展的技术世界中,时常会有一些重要的知识点、信息或细节被忽略或遗漏。《C#/.NET/.NET Core拾遗补漏》专栏我们将探讨一些可能被忽略或遗漏的重要知识点、信息或细节,以帮助大家更全面地了解这些技术栈的特性和发展方向。
|
2月前
|
SQL 数据库
使用ADO.NET查询和操作数据
使用ADO.NET查询和操作数据
12 0
|
2月前
|
开发框架 中间件 .NET
C# .NET面试系列七:ASP.NET Core
## 第一部分:ASP.NET Core #### 1. 如何在 controller 中注入 service? 在.NET中,在ASP.NET Core应用程序中的Controller中注入服务通常使用<u>依赖注入(Dependency Injection)</u>来实现。以下是一些步骤,说明如何在Controller中注入服务: 1、创建服务 首先,确保你已经在应用程序中注册了服务。这通常在Startup.cs文件的ConfigureServices方法中完成。例如: ```c# services.AddScoped<IMyService, MyService>(); //
92 0