首页 > 其他分享 >LINQ 查询添加自定义方法

LINQ 查询添加自定义方法

时间:2025-01-21 20:13:39浏览次数:1  
标签:IEnumerable 自定义 int double Median LINQ 查询 重载 方法

所有基于 LINQ 的方法都遵循两种类似的模式之一。 它们采用可枚举序列。 它们会返回不同的序列或单个值。 通过形状的一致性,可以通过编写具有类似形状的方法来扩展 LINQ。 事实上,自首次引入 LINQ 以来,.NET 库就在许多 .NET 版本中都获得了新的方法。 在本文中,你将看到通过编写遵循相同模式的自己的方法来扩展 LINQ 的示例。

通过向 IEnumerable<T> 接口添加扩展方法扩展可用于 LINQ 查询的方法集。 例如,除了标准平均值或最大值运算,还可创建自定义聚合方法,从一系列值计算单个值。 此外,还可创建一种方法,用作值序列的自定义筛选器或特定数据转换,并返回新的序列。 Distinct、Skip 和 Reverse 就是此类方法的示例。

扩展 IEnumerable<T> 接口时,可以将自定义方法应用于任何可枚举集合。 有关详细信息,请参阅扩展方法。

聚合方法可从一组值计算单个值。 LINQ 提供多个聚合方法,包括 Average、Min 和 Max。 可以通过向 IEnumerable<T> 接口添加扩展方法来创建自己的聚合方法。

下面的代码示例演示如何创建名为 Median 的扩展方法来计算类型为 double 的数字序列的中间值。

public static class EnumerableExtension
{
    public static double Median(this IEnumerable<double>? source)
    {
        if (source is null || !source.Any())
        {
            throw new InvalidOperationException("Cannot compute median for a null or empty set.");
        }
 
        var sortedList =
            source.OrderBy(number => number).ToList();
 
        int itemIndex = sortedList.Count / 2;
 
        if (sortedList.Count % 2 == 0)
        {
            // Even number of items.
            return (sortedList[itemIndex] + sortedList[itemIndex - 1]) / 2;
        }
        else
        {
            // Odd number of items.
            return sortedList[itemIndex];
        }
    }
}

使用从 IEnumerable<T> 接口调用其他聚合方法的方式为任何可枚举集合调用此扩展方法。

下面的代码示例说明如何为类型 double 的数组使用 Median 方法。

double[] numbers = [1.9, 2, 8, 4, 5.7, 6, 7.2, 0];
var query = numbers.Median();
 
Console.WriteLine($"double: Median = {query}");
// This code produces the following output:
//     double: Median = 4.85

可以重载聚合方法,以便其接受各种类型的序列。 标准做法是为每种类型都创建一个重载。 另一种方法是创建一个采用泛型类型的重载,并使用委托将其转换为特定类型。 还可以将两种方法结合。

可以为要支持的每种类型创建特定重载。 下面的代码示例演示 int 类型的 Median 方法的重载。

// int overload
public static double Median(this IEnumerable<int> source) =>
    (from number in source select (double)number).Median();

现在便可以为 integer 和 double 类型调用 Median 重载了,如以下代码中所示:

double[] numbers1 = [1.9, 2, 8, 4, 5.7, 6, 7.2, 0];
var query1 = numbers1.Median();
 
Console.WriteLine($"double: Median = {query1}");
 
int[] numbers2 = [1, 2, 3, 4, 5];
var query2 = numbers2.Median();
 
Console.WriteLine($"int: Median = {query2}");
// This code produces the following output:
//     double: Median = 4.85
//     int: Median = 3

还可以创建接受泛型对象序列的重载。 此重载采用委托作为参数,并使用该参数将泛型类型的对象序列转换为特定类型。

下面的代码展示 Median 方法的重载,该重载将 Func<T,TResult> 委托作为参数。 此委托采用泛型类型 T 的对象,并返回类型 double 的对象。

// generic overload
public static double Median<T>(
    this IEnumerable<T> numbers, Func<T, double> selector) =>
    (from num in numbers select selector(num)).Median();

现在,可以为任何类型的对象序列调用 Median 方法。 如果类型没有它自己的方法重载,必须手动传递委托参数。 在 C# 中,可以使用 lambda 表达式实现此目的。 此外,仅限在 Visual Basic 中,如果使用 Aggregate 或 Group By 子句而不是方法调用,可以传递此子句范围内的任何值或表达式。

下面的代码示例演示如何为整数数组和字符串数组调用 Median 方法。 对于字符串,将计算数组中字符串长度的中值。 该示例演示如何将 Func<T,TResult> 委托参数传递给每个用例的 Median 方法。

int[] numbers3 = [1, 2, 3, 4, 5];
 
/*
    You can use the num => num lambda expression as a parameter for the Median method
    so that the compiler will implicitly convert its value to double.
    If there is no implicit conversion, the compiler will display an error message.
*/
var query3 = numbers3.Median(num => num);
 
Console.WriteLine($"int: Median = {query3}");
 
string[] numbers4 = ["one", "two", "three", "four", "five"];
 
// With the generic overload, you can also use numeric properties of objects.
var query4 = numbers4.Median(str => str.Length);
 
Console.WriteLine($"string: Median = {query4}");
// This code produces the following output:
//     int: Median = 3
//     string: Median = 4

可以使用会返回值序列的自定义查询方法来扩展 IEnumerable<T> 接口。 在这种情况下,该方法必须返回类型 IEnumerable<T> 的集合。 此类方法可用于将筛选器或数据转换应用于值序列。

下面的示例演示如何创建名为 AlternateElements 的扩展方法,该方法从集合中第一个元素开始按相隔一个元素的方式返回集合中的元素。

// Extension method for the IEnumerable<T> interface.
// The method returns every other element of a sequence.
public static IEnumerable<T> AlternateElements<T>(this IEnumerable<T> source)
{
    int index = 0;
    foreach (T element in source)
    {
        if (index % 2 == 0)
        {
            yield return element;
        }
 
        index++;
    }
}

可使用从 IEnumerable<T> 接口调用其他方法的方式对任何可枚举集合调用此扩展方法,如下面的代码中所示:

string[] strings = ["a", "b", "c", "d", "e"];
 
var query5 = strings.AlternateElements();
 
foreach (var element in query5)
{
    Console.WriteLine(element);
}
// This code produces the following output:
//     a
//     c
//     e

 

标签:IEnumerable,自定义,int,double,Median,LINQ,查询,重载,方法
From: https://www.cnblogs.com/lgx5/p/18684346

相关文章

  • 点分治维护树上修改与查询
    点分治维护树上修改与查询具体方法就是将操作(修改与查询)离线,并打上时间戳,将其挂在点上,这样就可以考虑一个点到另一个点的贡献是否可以在其询问之前到达。对于所有的点分治都要效:避免算到同一个子树中,可以先整体计算后,在分别进入每个子树中,这样就可以不使用动态开点线段树了......
  • 计算机毕业设计Springboot实时校车查询微信小程序的设计与实现 基于Springboot框架的
    计算机毕业设计Springboot实时校车查询微信小程序的设计与实现3n85n858(配套有源码程序mysql数据库论文)本套源码可以先看具体功能演示视频领取,文末有联xi可分享随着城市化进程的加速和学校规模的不断扩大,校车服务已成为学生日常出行的重要方式。然而,传统的校车查询方式存......
  • 3. 使用sql查询csv/json文件内容,还能关联查询?
    1.简介我们在前面的文章提到了calcite可以支持文件系统的数据源适配,其实官方已经提供了相应的能力,其支持csv和json的查询适配,废话不多说,直接展示.2.Maven<!--calcite文件系统支持--><dependency><groupId>org.apache.calcite</groupId><artifactId>calc......
  • 使用 div 自定义 input 和 textarea
    1.为什么要自定义呢?原生的 input和textarea在某些特定场景下存在功能或兼容性限制,因此使用div元素自定义实现,突破原生输入框在样式、功能、兼容性上的限制。1、解决火狐浏览器换行问题某些版本的火狐浏览器中,原生 textarea 存在回车不换行而显示为空格的问题。这种......
  • [Tools] 自定义ESLint插件
    自定义ESLint插件ESLint插件主要是用来扩展ESLint本身没有的功能,这里包括扩展规则、扩展配置、扩展解析器。90%的ESLint插件都是以扩展规则为主,所以这些插件里面会包含大量的自定义规则。像这一类的插件,一般一条规则会对应一个JS文件,JS文件里面需要导出一个对象:module.expo......
  • SQL查询最近的年、月、周、日的统计数据
    <selectid="statTraffic"resultType="com.nuorui.module.platform.domain.vo.StatTotalVO"><![CDATA[SELECTCASEWHEN#{dateType}=0THENYEAR(date_series.generated_date)--......
  • sqlite3 mysql每秒查询性能
     数据库的查询性能(如每秒查询次数,QPS,即QueriesPerSecond)取决于多种因素,包括数据库引擎、硬件配置、查询复杂度、数据量以及系统优化程度等。以下是对SQLite和MySQL每秒查询能力的比较和分析:SQLite每秒查询能力性能特点:SQLite是一个轻量级、文件系统级的数......
  • MySQL架构总览_查询执行流程_SQL解析顺序
    目录MySQL架构总览查询执行流程连接处理结果SQL解析顺序准备工作FROMWHEREGROUPBYHAVINGSELECTORDERBYLIMIT总结参考书籍MySQL架构总览架构最好看图,再配上必要的说明文字。下图根据参考书籍中一图为原本,再在其上添加上了自己的理解。从上图中我们可以看到,整个架构分为两......
  • Mybatis实现RBAC权限模型查询
    RBAC(Role-BasedAccessControl,基于角色的访问控制)是一种常用的权限管理模型,它通过角色来管理用户权限。在RBAC模型中,权限是授予角色的,用户通过扮演某些角色获得相应的权限。本文将介绍如何使用MyBatis实现RBAC权限模型的查询。一、RBAC权限模型简介核心概念用户(User) :系统的......
  • ROS自定义消息类型
    1.std_msgs消息类型如下:来源:std_msgsMsg/SrvDocumentationstd_msgs的消息类型大致可以分为:基础类型,如Bool数组类型,如Float32MultiArray结构体类型。如Header我们可以在ROSIndex这里查到各种类型的消息包。std_msgs相对比较常用,包含各种基本的消息类型,我们在构建自......