【.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也提供丰富的操作函数,在实际的使用中根据不同应用常见选择恰当的方法。

目录
相关文章
|
23天前
|
开发框架 .NET 开发者
简化 ASP.NET Core 依赖注入(DI)注册-Scrutor
Scrutor 是一个简化 ASP.NET Core 应用程序中依赖注入(DI)注册过程的开源库,支持自动扫描和注册服务。通过简单的配置,开发者可以轻松地从指定程序集中筛选、注册服务,并设置其生命周期,同时支持服务装饰等高级功能。适用于大型项目,提高代码的可维护性和简洁性。仓库地址:&lt;https://github.com/khellang/Scrutor&gt;
39 5
|
2月前
|
开发框架 .NET C#
在 ASP.NET Core 中创建 gRPC 客户端和服务器
本文介绍了如何使用 gRPC 框架搭建一个简单的“Hello World”示例。首先创建了一个名为 GrpcDemo 的解决方案,其中包含一个 gRPC 服务端项目 GrpcServer 和一个客户端项目 GrpcClient。服务端通过定义 `greeter.proto` 文件中的服务和消息类型,实现了一个简单的问候服务 `GreeterService`。客户端则通过 gRPC 客户端库连接到服务端并调用其 `SayHello` 方法,展示了 gRPC 在 C# 中的基本使用方法。
46 5
在 ASP.NET Core 中创建 gRPC 客户端和服务器
|
1月前
|
开发框架 缓存 .NET
GraphQL 与 ASP.NET Core 集成:从入门到精通
本文详细介绍了如何在ASP.NET Core中集成GraphQL,包括安装必要的NuGet包、创建GraphQL Schema、配置GraphQL服务等步骤。同时,文章还探讨了常见问题及其解决方法,如处理复杂查询、错误处理、性能优化和实现认证授权等,旨在帮助开发者构建灵活且高效的API。
27 3
|
8天前
|
开发框架 算法 中间件
ASP.NET Core 中的速率限制中间件
在ASP.NET Core中,速率限制中间件用于控制客户端请求速率,防止服务器过载并提高安全性。通过`AddRateLimiter`注册服务,并配置不同策略如固定窗口、滑动窗口、令牌桶和并发限制。这些策略可在全局、控制器或动作级别应用,支持自定义响应处理。使用中间件`UseRateLimiter`启用限流功能,并可通过属性禁用特定控制器或动作的限流。这有助于有效保护API免受滥用和过载。 欢迎关注我的公众号:Net分享 (239字符)
25 0
|
2月前
|
XML 开发框架 .NET
.NET 9 中 LINQ 新增功能实操
.NET 9 中 LINQ 新增功能实操
|
3月前
|
开发框架 JavaScript 前端开发
一个适用于 ASP.NET Core 的轻量级插件框架
一个适用于 ASP.NET Core 的轻量级插件框架
|
6天前
|
监控 前端开发 API
一款基于 .NET MVC 框架开发、功能全面的MES系统
一款基于 .NET MVC 框架开发、功能全面的MES系统
|
4月前
|
开发框架 前端开发 JavaScript
ASP.NET MVC 教程
ASP.NET 是一个使用 HTML、CSS、JavaScript 和服务器脚本创建网页和网站的开发框架。
51 7
|
4月前
|
存储 开发框架 前端开发
ASP.NET MVC 迅速集成 SignalR
ASP.NET MVC 迅速集成 SignalR
85 0
|
5月前
|
开发框架 前端开发 .NET
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
66 0