当前位置: 首页 > news >正文

C#`Array`进阶

一、数组方法进阶(Array类核心方法解析)

该部分主要介绍Array类的静态方法与实例方法,核心是高阶函数(参数为函数的方法)的应用,通过回调函数实现灵活的数组查询与操作。

1. 核心静态方法(Array.XXX

静态方法需通过Array类直接调用,主要用于数组查询、判断、遍历等,参数常包含 “回调函数”(定义查询条件)。

方法作用关键参数示例场景
Find从前向后查找第一个满足条件的元素数组 + 回调函数(返回bool,表示元素是否符合条件)查找第一个不满 18 岁的年龄(Array.Find(ages, FindSamll18)
FindLast从后向前查找第一个满足条件的元素Find查找最后一个能被 3 和 5 整除的数(Array.FindLast(ages, Find35)
FindIndex从前向后查找第一个满足条件的元素的索引Find查找第一个能被 3 和 5 整除的数的索引(Array.FindIndex(ages, Find35)
FindLastIndex从后向前查找第一个满足条件的元素的索引Find查找最后一个能被 3 和 5 整除的数的索引(Array.FindLastIndex(ages, Find35)
TrueForAll判断数组所有元素是否都满足条件(全满足返回true数组 + 回调函数判断所有数字是否都是偶数(Array.TrueForAll(nums, FindEven)
Exists判断数组至少有一个元素满足条件(有一个满足返回true数组 + 回调函数判断是否存在偶数(Array.Exists(nums, FindEven)
ForEach遍历数组,对每个元素执行指定操作(替代for/foreach的专用遍历)数组 + 回调函数(无返回值,执行操作)遍历数组并对每个元素 + 1 输出(Array.ForEach(nums, Each)
2. 实例方法(数组对象.XXX)

实例方法通过数组对象调用,主要用于数组复制、元素操作、属性查询等。

方法作用示例
CopyTo将当前数组元素复制到目标数组的指定位置str1.CopyTo(str2, 1)(将str1str2[1]开始复制)
GetLength获取多维数组指定维度的长度(一维数组等效于Lengthstr1.GetLength(0)(返回一维数组str1的长度)
GetValue/SetValue获取 / 设置指定索引的元素值str1.GetValue(0)(获取str1[0]);str1.SetValue("郑爽", 1)(设置str1[1]
Contains判断数组是否包含指定元素(需引入System.Linqstr1.Contains("李云迪")(判断是否包含 “李云迪”)
3. 代码核心分析
  • 高阶函数与回调函数Find/TrueForAll等方法的第二个参数是 “回调函数”(如FindSamll18),这些方法内部会循环数组,将每个元素传入回调函数,根据返回值判断是否满足条件。这种设计让数组操作更灵活(同一方法可通过不同回调实现不同查询)。

  • 示例逻辑: 例如Array.Find(ages, FindSamll18)的执行流程:循环ages数组,每次将元素传入FindSamll18,若返回true(元素 < 18),则立即返回该元素。 代码中FindSamll18/FindOdd等回调函数,本质是将 “查询条件” 封装为可复用的逻辑。

二、Lambda 表达式(匿名函数的简化语法)

Lambda 表达式是匿名函数的语法糖,用于简化回调函数的定义,尤其在高阶函数中可大幅减少代码量。

1. 语法演进(从完整到简写)

Lambda 的核心是=>(Lambda 运算符,读作 “goes to”),左侧为参数,右侧为函数体。语法逐步简化如下:

形式示例代码说明
完整形式Func<int, int, int> fn1 = (int a, int b) => { return a + b; };显式指定参数类型,函数体用{}包裹,包含return
省略参数类型Func<int, int, int> fn2 = (a, b) => { return a + b; };编译器自动推断参数类型(基于委托类型Func<int, int, int>
单个参数省略括号Func<int, int> fn3 = a => { return a + 13; };仅一个参数时,可省略()
单表达式省略{}returnFunc<int, int> fn4 = a => a + 13;函数体仅一个表达式时,自动返回表达式结果,无需{}return
2. 在数组方法中的应用

Lambda 表达式最常用的场景是替代命名回调函数,让代码更紧凑。例如:

命名函数方式Lambda 表达式方式说明
Array.Find(ints, FindEven)Array.Find(ints, v => v % 2 == 0)用 Lambda 直接定义 “偶数条件”,替代单独定义的FindEven函数
Array.FindIndex(strings, FindLength2)Array.FindIndex(strings, v => v.Length == 2)直接在参数中定义 “长度为 2” 的条件,无需额外函数
3. 核心优势
  • 简化代码:省去命名函数的定义,将条件逻辑直接写在调用处,减少跳转。

  • 增强可读性:查询条件与方法调用在同一位置,逻辑更连贯(如v => v.StartsWith("吴")直观表示 “以吴开头”)。

  • 灵活适配:针对一次性使用的简单条件,无需定义复用函数,降低冗余。

三、数组排序(冒泡排序、选择排序与Array.Sort

排序是数组操作的核心场景,这里介绍两种基础排序算法及Array.Sort的用法。

1. 冒泡排序

原理:通过相邻元素的比较与交换,使最大元素逐步 “冒泡” 到数组尾部,重复缩小范围直至排序完成。

  • 核心代码(优化版):

    int[] ints1 = { 1, 8, 6, 2, 5, 4, 10, 3 };
    for (int i = 0; i < ints1.Length; i++)
    {// 内层循环范围:0 ~ 长度-1-i(排除已排序的尾部元素)for (int j = 0; j < ints1.Length - 1 - i; j++){if (ints1[j] > ints1[j + 1]){(ints1[j], ints1[j + 1]) = (ints1[j + 1], ints1[j]); // 交换元素}}
    }

  • 优化点:内层循环j < ints1.Length - 1 - i,每次排除已排序的尾部元素(减少无效比较)。

  • 时间复杂度:O (n²)(适合小规模数据)。

2. 选择排序

原理:每次从剩余元素中找到最小值,与未排序部分的首个元素交换,逐步构建有序序列。

  • 核心代码:

    for (int i = 0; i < ints1.Length; i++)
    {int minIndex = i; // 记录最小值索引for (int j = i + 1; j < ints1.Length; j++){if (ints1[j] < ints1[minIndex]) minIndex = j; // 更新最小值索引}if (minIndex != i) // 交换最小值到当前位置{(ints1[i], ints1[minIndex]) = (ints1[minIndex], ints1[i]);}
    }

  • 优势:交换次数少(每次外层循环仅交换 1 次),比冒泡排序略高效。

  • 时间复杂度:O (n²)(同样适合小规模数据)。

3. Array.Sort(内置排序)

C# 提供Array.Sort静态方法,默认升序,支持通过 Lambda 自定义排序规则。

  • 基础用法:

    int[] ints = { 3, 1, 4, 2 };
    Array.Sort(ints); // 默认升序:[1, 2, 3, 4]
  • 自定义排序(Lambda 比较器):

    // 升序:a - b(返回负数时a在前,正数时b在前)
    Array.Sort(ints, (a, b) => a - b); 
    // 降序:b - a
    Array.Sort(ints, (a, b) => b - a); 
  • 比较器逻辑:Lambda 返回值决定元素顺序 —— 负数(a 在前)、正数(b 在前)、0(位置不变)。

4. 排序算法对比
维度冒泡排序选择排序Array.Sort(内置)
时间复杂度O(n²)O(n²)O (n log n)(快排 / 混合排序)
交换次数多(每次比较可能交换)少(每次外层循环最多交换 1 次)内部优化,效率高
适应性可优化(检测到有序时提前终止)不可(固定遍历次数)自动适配数据规模
适用场景小规模数据、教学演示小规模数据、交换成本高的场景实际开发(高效、简洁)

四、作业实现与分析(People数组查询)

基于People数组的 5 个查询需求,结合前面的数组方法与 Lambda 表达式实现,分析如下:

1. 定义People类与数组
class People
{public enum ESex { man, woman } // 性别枚举public string Name { get; set; } // 姓名public int Age { get; set; } // 年龄public ESex Sex { get; set; } // 性别
}
​
// 初始化数组
People[] peoples = {new People { Name="吴亦凡", Age=18, Sex=People.ESex.man },new People { Name="郑爽", Age=22, Sex=People.ESex.woman },new People { Name="李云迪", Age=21, Sex=People.ESex.man },new People { Name="蔡徐坤", Age=32, Sex=People.ESex.man },new People { Name="权志龙", Age=8, Sex=People.ESex.man },new People { Name="杨幂", Age=18, Sex=People.ESex.woman }
};
2. 需求实现与分析
需求实现代码核心方法 / 逻辑
1. 查询所有男性var allMen = peoples.Where(p => p.Sex == People.ESex.man).ToList();Where(LINQ 方法):筛选所有满足 “性别为男性” 的元素,返回IEnumerable<People>,通过ToList()转为列表。
2. 查询第一个女性var firstWoman = Array.Find(peoples, p => p.Sex == People.ESex.woman);Array.Find:从前向后查找第一个 “性别为女性” 的元素。
3. 判断是否全为成年人(≥18)bool allAdults = Array.TrueForAll(peoples, p => p.Age >= 18);TrueForAll:检查所有元素是否满足 “年龄≥18”,因权志龙 8 岁,返回false
4. 计算年龄平均值double avgAge = peoples.Average(p => p.Age);Average(LINQ 方法):计算所有元素 “Age” 属性的平均值,结果为(18+22+21+32+8+18)/6 ≈ 19.83
5. 查询第一个未成年男性(<18)var firstMinorMan = Array.Find(peoples, p => p.Sex == People.ESex.man && p.Age < 18);Array.Find:筛选 “男性且年龄 < 18” 的第一个元素(权志龙)。
3. 关键方法选择依据
  • 批量查询(所有男性):用Where(返回所有满足条件的元素)。

  • 单个元素查询(第一个女性 / 未成年男性):用Array.Find(高效返回首个匹配元素)。

  • 全量判断(是否全为成年人):用TrueForAll(一次性验证所有元素)。

  • 数值计算(平均年龄):用Average(LINQ 提供的聚合方法,简化计算)。

http://www.dtcms.com/a/285771.html

相关文章:

  • Java全栈面试实录:从Spring Boot到AI大模型的深度解析
  • 现代R语言机器学习:Tidymodel/Tidyverse语法+回归/树模型/集成学习/SVM/深度学习/降维/聚类分类与科研绘图可视化
  • 135. Java 泛型 - 无界通配符
  • 【PTA数据结构 | C语言版】二叉堆的朴素建堆操作
  • 防爆手机是什么?能用普通手机改装吗?
  • 国产替代:ASP4644在电信通信设备中的测试与应用前景
  • 上网行为管理-web认证服务
  • Kotlin封装
  • JVM常用运行时参数说明
  • 机器人行业10年巨变从协作机器人到具身智能的萌芽、突破和成长——从 Automatic慕尼黑10 年看协作机器人到具身智能的发展
  • 基于单片机汽车驾驶防瞌睡防疲劳报警器自动熄火设计
  • Git--本地仓库的学习
  • 深入解析Linux系统启动全流程
  • 【Leecode 随笔】
  • 系统分析师-计算机系统-指令系统多处理机系统
  • 【案例教程】基于现代R语言【Tidyverse、Tidymodel】的机器学习方法与案例分析实践技术应用
  • 如何将 iPhone 备份到笔记本电脑?
  • mac mlx大模型框架的安装和使用
  • Web前端入门:JavaScript async await 的异步任务进化之路
  • 深入解析文本分类技术全景:从特征提取到深度学习架构
  • 【项目】MCP+GraphRAG搭建检索增强智能体
  • -lstdc++与-static-libstdc++的用法和差异
  • 谈进程间通信
  • 从Hyperliquid到AILiquid:一场从极致性能到策略智能的迭代
  • 硅和锗二极管的主要区别
  • 参会邀请!2025世界人工智能大会合合信息技术交流日报名启动!
  • 深入理解 Linux 进程间通信
  • Linux——库的制作与原理
  • Linux 信号与中断 详解
  • ali linux 上安装swagger-codegen