From 541fb665effd17795c582fe54b06ea381c526f83 Mon Sep 17 00:00:00 2001 From: bicijinlian Date: Thu, 3 Apr 2025 00:36:02 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=8A=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 数据切片.linq | 213 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 数据切片.linq diff --git a/数据切片.linq b/数据切片.linq new file mode 100644 index 0000000..ddec4c6 --- /dev/null +++ b/数据切片.linq @@ -0,0 +1,213 @@ + + Microsoft.CodeAnalysis.CSharp + Microsoft.Extensions.Configuration + Microsoft.Extensions.Configuration.Binder + Microsoft.Extensions.Configuration.CommandLine + Microsoft.Extensions.Configuration.EnvironmentVariables + Microsoft.Extensions.Configuration.FileExtensions + Microsoft.Extensions.Configuration.Ini + Microsoft.Extensions.Configuration.Json + Microsoft.Extensions.Configuration.UserSecrets + Microsoft.Extensions.Configuration.Xml + Microsoft.Extensions.DependencyInjection + Microsoft.Extensions.Logging + Microsoft.Extensions.Logging.Configuration + Microsoft.Extensions.Options + Newtonsoft.Json + xunit + Microsoft.Extensions.Configuration + Microsoft.Extensions.Configuration.CommandLine + Microsoft.Extensions.Configuration.EnvironmentVariables + Microsoft.Extensions.Configuration.Memory + Microsoft.Extensions.DependencyInjection + Microsoft.Extensions.DependencyInjection.Extensions + Microsoft.Extensions.FileProviders.Internal + Microsoft.Extensions.FileProviders.Physical + Microsoft.Extensions.Logging + Microsoft.Extensions.Logging.Abstractions + Microsoft.Extensions.Logging.Configuration + Microsoft.Extensions.Options + Microsoft.Extensions.Primitives + Newtonsoft.Json + Newtonsoft.Json.Converters + Newtonsoft.Json.Linq + Newtonsoft.Json.Serialization + System.Threading.Tasks + true + true + true + + +/* + 数据切片学习 +*/ + +/* + 相关类及命名空间 + System.ArraySegment 数组切片 + System.Index 索引对象 + System.Range 范围对象,不支持多维数组 + System.Linq 结构化查询 +*/ + +// 切片语法糖:C# 8+支持 + +{ // ^ 表示倒数:从尾部向前数,并且从1开始,索引必须是正整数 + + var names = new string[] { "潘安琪", "贺睿", "邹致远", "蔡子韬", "江睿", "范震南", "何詩涵", "郝岚", "尹震南", "萧詩涵" }; + + //倒数第1个:索引从1开始,而不是0开始(为0则异常) + Console.WriteLine($"倒数第1个:{names[^1]} "); + Console.WriteLine($"倒数第2个:{names[^2]} "); +} + +{ // .. 表示范围:[开始索引..结束索引] + + var names = new string[] {"潘安琪", "贺睿", "邹致远", "蔡子韬", "江睿", "范震南", "何詩涵", "郝岚", "尹震南", "萧詩涵"}; + + //.. 表示所有 + names[..].Dump(); + + //开始索引s.. 表示第s个开始,直到结尾 + names[1..].Dump(); + + //开始索引s..结束索引e 表示第m个开始,直到s结束e(不包括e) + names[1..5].Dump(); + names[0..1].Dump(); + + //与^组合使用 + names[^2..].Dump(); //倒数第2个开始,直到结尾(倒数第2个和倒数第1个) + names[..^2].Dump(); //第1个开始,倒数第2个结束(去掉尾部2项) + names[5..^2].Dump(); //第6个开始,倒数第2个结束(去掉前面5个和尾部2项) + names[^2..^1].Dump(); //倒数第2个开始,倒数第1个结束(倒数第2个) +} + +{ // .. 范围:可用 Range 对象表示,第n个可用 System.Index 索引对象表示 + var names = new string[] {"潘安琪", "贺睿", "邹致远", "蔡子韬", "江睿", "范震南", "何詩涵", "郝岚", "尹震南", "萧詩涵"}; + + System.Range r1= ..; + names[r1].Dump(); + + System.Range r2 = new System.Range(); //默认项数为0的切片,不是null而是Empty切片 + names[r2].Dump(); + + var start = new Index(0);//第1个 + var end = new Index(1,true); //倒序索引,倒数第1个 + + //“索引对象” 组成 “范围对象” + var query = new System.Range(start,end); + + //切片使用 “范围对象” + var segment = names[query]; + segment.Dump(); +} + +/* + 重要特性 +*/ + +{ + //1、切片是由原数组创建的新数组,两个数组本身互相独立、互不影响; + // 如果数据项是引用对象,因为两个数组虽然各自独立,但引用对象是同一个,这时引用对象本身的修改,会影响两个数组; + var ages = new int[] {1, 2, 3, 4, 5}; + var s1 = ages[..2]; + //改变切片项的值,原数组保持不变 + s1[0]=-100; + + //两个数组本身互相独立、互不影响 + (ages[0] == s1[0]).Dump(); + + //数据项是引用对象,对引用对象的修改,都影响 + var persons = new Person[] + { + new Person(){Name = "潘安琪", Age = 20}, + new Person(){Name = "贺睿", Age = 36}, + new Person(){Name = "邹致远", Age = 65}, + new Person(){Name = "蔡子韬", Age = 85}, + new Person(){Name = "江睿", Age = 24}, + new Person(){Name = "范震南", Age = 29}, + new Person(){Name = "何詩涵", Age = 11}, + new Person(){Name = "郝岚", Age = 65}, + new Person(){Name = "尹震南", Age = 85}, + new Person(){Name = "萧詩涵", Age = 62}, + }; + + var segment = persons[1..3]; + + //persons和segment本身互相独立 + //但 persons[1]segment[0] 是同一个 Person 地址,所以改变一个引用的 Person 时,另一个也引用了同一个对象自然就变 + + //修改对象属性值 + segment[0].Name="修改"; + + Console.WriteLine($"名称相同:{segment[0].Name == persons[1].Name}"); + +} + +/* + 切片与System.Span System.Memory 组合使用 +*/ +{ + //原数组使用AsSpan方法;而不应把切片直接给Span + //把切片直接给Span,此时切片与原数组独立,相当于Span了整个切片而与原数组脱离关系 + var source = new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + + //AsSpan方法,可以把指定切片语法的部分转为Span,这样原数据与Span相关,才能提高性能 + var span1 = source.AsSpan(0..3); + Console.WriteLine($"Span是原数组的一部分, source[0]{(source[0]==span1[0]?"==":"!=")}span1[0]"); +} + + +/* + 切片与 “列表模式匹配” +*/ +{ + int[] source = new int[] { 1, 3, 5, 7, 9 }; + //传统switch语句:switch (变量) => 变量在后,Case 分支语句,目的是选择执行Case分支语句块,无返回值。 + switch (source) + { + case [var a, .., 5]://Case后可以使用各种模式匹配 + //业务逻辑 + break; + } + + //模式匹配switch语句:判断量 switch (变量)=>变量在前,lamda分支语句,目的是选择执行lamda分支语句块,有返回值 + + //使用弃元,放弃返回值 + _ = source switch + { + [1, ..] => 2, //因为是lamda表达式,所以只能是单条返回语句.不能加{}执行多语句 + [..] => 3, + _ => 2, + }; + //返回值给变量 + int t = source switch + { + [1, .., 9] a => a[0], + int[] { Length: >= 5} item => item[4], + int[] =>1, + _ => 0, + }; + + //作为方法体,返回值给方法执行结果 + static int GetSourceLabel(IEnumerable source) => source switch + { + string[] {Length:>0} =>1, + int[] i and [var a, ..] => 1, + Array array => 2, + ICollection{Count:>0} collection => 2, + _ => 0, + }; +} + +class Person +{ + public string Name { get; set;} + + public int Age {get;set;} +} + + + + +