【.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月前
|
存储 开发框架 JSON
ASP.NET Core OData 9 正式发布
【10月更文挑战第8天】Microsoft 在 2024 年 8 月 30 日宣布推出 ASP.NET Core OData 9,此版本与 .NET 8 的 OData 库保持一致,改进了数据编码以符合 OData 规范,并放弃了对旧版 .NET Framework 的支持,仅支持 .NET 8 及更高版本。新版本引入了更快的 JSON 编写器 `System.Text.UTF8JsonWriter`,优化了内存使用和序列化速度。
|
10天前
|
XML 开发框架 .NET
.NET 9 中 LINQ 新增功能实操
.NET 9 中 LINQ 新增功能实操
|
2月前
|
开发框架 监控 前端开发
在 ASP.NET Core Web API 中使用操作筛选器统一处理通用操作
【9月更文挑战第27天】操作筛选器是ASP.NET Core MVC和Web API中的一种过滤器,可在操作方法执行前后运行代码,适用于日志记录、性能监控和验证等场景。通过实现`IActionFilter`接口的`OnActionExecuting`和`OnActionExecuted`方法,可以统一处理日志、验证及异常。创建并注册自定义筛选器类,能提升代码的可维护性和复用性。
|
2月前
|
开发框架 .NET 中间件
ASP.NET Core Web 开发浅谈
本文介绍ASP.NET Core,一个轻量级、开源的跨平台框架,专为构建高性能Web应用设计。通过简单步骤,你将学会创建首个Web应用。文章还深入探讨了路由配置、依赖注入及安全性配置等常见问题,并提供了实用示例代码以助于理解与避免错误,帮助开发者更好地掌握ASP.NET Core的核心概念。
100 3
|
1月前
|
开发框架 JavaScript 前端开发
一个适用于 ASP.NET Core 的轻量级插件框架
一个适用于 ASP.NET Core 的轻量级插件框架
|
1月前
|
开发框架 .NET 开发工具
.NET 9 中 LINQ 新增的功能
.NET 9 中 LINQ 新增的功能
|
2月前
|
开发框架 NoSQL .NET
利用分布式锁在ASP.NET Core中实现防抖
【9月更文挑战第5天】在 ASP.NET Core 中,可通过分布式锁实现防抖功能,仅处理连续相同请求中的首个请求,其余请求返回 204 No Content,直至锁释放。具体步骤包括:安装分布式锁库如 `StackExchange.Redis`;创建分布式锁服务接口及其实现;构建防抖中间件;并在 `Startup.cs` 中注册相关服务和中间件。这一机制有效避免了短时间内重复操作的问题。
|
开发框架 前端开发 .NET
ASP.NET Core 核心特性学习笔记「下」
ASP.NET Core 核心特性学习笔记「下」
|
开发框架 前端开发 中间件
ASP.NET Core 核心特性学习笔记「上」
ASP.NET Core 核心特性学习笔记「上」
|
SQL 机器学习/深度学习 Cloud Native
.NET 云原生架构师训练营(模块二 基础巩固 EF Core 更新和迁移)--学习笔记
- 状态 - 自动变更检测 - 不查询删除和更新 - 并发
252 0
.NET 云原生架构师训练营(模块二 基础巩固 EF Core 更新和迁移)--学习笔记
下一篇
无影云桌面