目录
一、一维数组
二、多维数组
三、交错数组
四、存储引用类型
五、数组的属性和方法
六、数组的高级方法
七、Lambda表达式
八、自己实现find功能
九、排序
1、冒泡排序
2、选择排序
3、sort排序
1.第一种
2.第二种
3.第二种
一、一维数组
(1)数组:存储相同类型的数据的容器,并且数组是有大小固定的,操作数组时候都是通过索引值进行操作;
(2)这个索引值也可以称为下标,索引值从0开始,长度从1开始,最大的索引值=长度减1,并且数组都是顺序的;
(3)数组都是基于Array的;(4)定义数组:数据类型[ ] 变量名;
int[] ages;//定义整型数组,默认值为0 bool[] sexs;//定义布尔数组 默认值为false string[] names;//定义字符串数组 默认值null char[] chars ; // 定义字符数组 ,默认值是\0 //赋值 //ages = new int[10];//赋值长度为10空数组 // sexs = new bool[10]; //赋值的其他方式 names = new string[5] {"张三", "张三" ,"张三", "张三", "张三" };//赋值的时候指定长度和初始化元素 ages = new int[] { 1, 2, 3 };//不指定长度 长度由元素个数确定 int[] nums = { 1, 2, 3 }; //字面量定义数组 string[] msgs = new string[100]; //修改数组里面对应位置的元素 //msgs[0] = "张三"; //msgs[1] = "搜索"; // msgs[100] = "ss"; //索引超出了数组界限。//添加多个数据 for (int i = 0; i < msgs.Length; i++) // msgs.Length 数组长度的属性 { msgs[i] = i+"深度";//给数组每一个元素进行赋值 } //取出一个数组元素 通过下标取出元素 Console.WriteLine(msgs[99]); //取出多个元素,使用for循环遍历 for (int i = 0; i < msgs.Length; i++) { Console.WriteLine(msgs[i]+"--------"); } //使用foreach进行遍历 item = msgs[i] //item 每一个元素 foreach (string item in msgs) { Console.WriteLine(item+"++++"); }for和foreach的区别:
(1) foreach简单
(2) 缺点: 不能通过i访问元素 ,不能访问元素所在的位置
二、多维数组
c#数组可以定义成一维数组 也可以定义成多维数组,
(1)定义二维数组可以理解为几行几列
int[,] ints=new int[2,3];定义一个三维数组分为1维空间 2维空间 3维空间
int[,,] ints1 = new int[2, 3, 4];(2)定义多维数组
int[n-1个逗号] 变量名 = new int[每个维度的长度,,]
//1 定义二维数组,不用指定维度的长度,按照数据自动推导 int[,] ints = new int[,] { {1,2,3 }, {4,5,6}, {7,8,9}, };// 定义一个三维数组的不带长度的定义方式 // 外数组 有俩个{} 长度为2 // 中间数组 有一个{} 长度为1 // 最内的数组 有三个长度 长度位3 int[,,] ints1 = new int[,,] { { { 1,2,3 }, { 1,2,3, }, }, { { 1,2,113 }, { 1,2,339 } }, }; Console.WriteLine(ints1.GetLength(0)+"----");// 2 Console.WriteLine(ints1.GetLength(1)); // 2 Console.WriteLine(ints1.GetLength(2));//3 Console.WriteLine(ints1[1,1,2]+"??????????");/339//2 定义二维的字符串数组 string[,] strings = new string[,] { {"孙悟空","猪八戒","沙和尚" }, {"刘备","曹操","孙权" }, {"宋江","林冲","吴用" }, {"贾宝玉","林黛玉","薛宝钗"} }; Console.WriteLine(strings.Length); // 32位总长度12 Console.WriteLine(strings.LongLength);//64位总长度12 Console.WriteLine(strings.Rank);//2 维度数 Console.WriteLine(strings.GetLength(0)); //对应维度的长度 4 Console.WriteLine(strings.GetLength(1)); // 对应二维维度的长度 3 //取出指定位置的元素 多维数组[每个维度的索引] Console.WriteLine(strings[0,0]);//孙悟空 Console.WriteLine(strings[0,1]);//猪八戒 // strings[3, 1] = "王熙凤"; 修改指定位置的数据 Console.WriteLine(strings[3,1]);//林黛玉//for循环进行取出所有的 for (int i = 0; i < strings.GetLength(0); i++) //遍历1维数据 相当于行 4 { for (int j= 0; j < strings.GetLength(1); j++)//遍历2位数据 相当于列 3 { Console.Write(strings[i,j]);//i=0 j = 0 1 2 } Console.WriteLine(""); } //使用foreach进行遍历 foreach (var item in strings) { Console.WriteLine(item + "--------------"); }//通过for循环添加 string[,] names = new string[5, 10]; //初始化的时候不指定数据的元素 for (int i= 0; i<names.GetLength(0); i++) { for (int j = 0; j < names.GetLength(1); j++) { names[i, j] = $"行:{i} 列:{j}"; //动态修改数组数据 } } Console.WriteLine(names[3,9]);//行:3 列:9 foreach (var item in names) { Console.WriteLine(item + "++++++++"); }//练习: 定义一个二维数组 叫做 arr3 //arr3[0,3] ====> 10 //arr3[1,2] ====> 20 //arr3[2,2] ====> 30 int[,] ints2 = new int[,] { {0,0,0,10}, {0,0,20,0 }, {0,0,30,0 } }; //随机昵称 string[] xings = {"赵","钱","孙","李","诸葛" ,"夏侯","东方","欧阳"}; //姓数组 string[] names1 = { "亮", "娜娜", "月初", "惇", "匡胤", "多多", "权", "世民" }; Random rnd = new Random(); //把随机数作为数组的下标 int index = rnd.Next(0, xings.Length); //随机姓氏 int index1 = rnd.Next(0, names1.Length); // 随机名字 Console.WriteLine(xings[index] + names1[index1]);三、交错数组
(1)交错数组:大数组包含小数组,也就是数组里面的元素还是数组;
(2)交错数组和多维数组的区别: 交错数组每一个长度都可以不同,多维数组每一个维度长度都必须相同。
int[] i1s= new int[4] {1,2,3,4}; //一维数组 int[] i2s = new int[] { 1, 2, 3, 4 ,5};//一维数组 //俩层交错数组 int[][] 变量= new int[][]{}初始化 int[][] ints = new int[][] { i1s, //长度4 i2s, //长度5 new int[]{1,2,3,4,5,999}//长度6 }; //取元素值(分开取值) int[] arr = ints[1]; //i2s这个数组 int a = arr[4];//再从arr数组取出对应的值 Console.WriteLine(a); // 一句话取值 Console.WriteLine(ints[2][5]);//999 ints[1][2] = 888;//修改指定位置的元素 //使用for循环进行取值 for (int i = 0; i < ints.Length; i++) //遍历最外层数组,长度3 { Console.WriteLine(ints[i].Length+"sssssss");//每个小数组的长度 //ints[i]// 最外层数组的每一个元素,又是数组,再次遍历每一个数组 for (int j = 0; j < ints[i].Length; j++) { //ints[i][j] 所有元素值 Console.WriteLine($"({i}:{j}={ints[i][j]})" );//i=0 j = 0 1 2 3 ;i=1 j =0 1 2 3 4 ;i=2 j= 0 1 2 3 4 5 } } //使用foreach进行遍历 foreach (int[] item in ints)//遍历外层的数组 item又是一个数组 { foreach (int item1 in item)// 再次遍历内层每个数组 { Console.WriteLine(item1+"+++++++"); } }四、存储引用类型
//数组是引用类型 int[] arr = new int[] { 1, 2, 3 }; int[] arr2 = arr;//赋值 arr[0] = 999; Console.WriteLine(arr2[0]);//999 //存储10个对象类型 //数组类型定义:数组类型[] 变量名= new 数组类型[长度]; People[] p1s = new People[10];//长度10 // p1s[0].Name for (int i = 0; i < p1s.Length; i++) { People p1 = new People() { Name = "学生" + i };//构建对象给属性赋值 //添加到数组里面 p1s[i] = p1; } //验证 遍历 foreach (People p in p1s) // p1s数组存储的是People类型 { Console.WriteLine(p.Name+"+++"); } Console.WriteLine(string.Join("-",arr));//999-2-3 按照分隔符 进行分割数组里面元素//以下了解 People p2 = new People(); p2.Name = "sss";//People可以使用name Student s1 = new Student(); s1.Name = "ss";//Student继承People 所以可以使用Name object[] os = new object[] {1,2,true,"ss",new People() { Name="1"} }; Console.WriteLine(10.GetType().BaseType.BaseType+"sssssssssss");//getType().获取类型 BaseType的基类 //能不能使用父类的类型的数组存储子类的对象? //可以,在这个过程就发生了协变 People[] ps = new People[] { new People(){Name="zs"}, new People(){Name="ls"}, new Student(){Name="ww"} }; People[] ps2 = ps; //把ps数组赋值给ps2 ps2[2].Name ="郑爽"; Console.WriteLine(ps[2].Name);//郑爽五、数组的属性和方法
//1 Array.Clear(nums,0,nums.Length);// 从0开始 清空长度为nums.Length Array.Clear(nums, 1, 3); Console.WriteLine(string.Join("-",nums));//Join 把数组的元素按照字符串方式进行打印//2 copy方法 int[] nums1 = { 1, 2, 3, 4 }; int[] nums2 = new int[nums1.Length]; //参数1 要复制的数组 //参数2 要复制的目标数组 //参数3 赋值的长度 Array.Copy(nums1,nums2,4); nums1[0] = 100;//修改原数组的元素 是否影响nums2数组, //如果数组存储的是值类型,使用copy方法进行复制时候 ,修改一个,不会影响另一个 //如果数组存储的是引用类型,使用copy方法进行复制时候 ,修改一个,会影响另一个 Console.WriteLine(string.Join("-", nums2)); //参数1 要复制的数组 //参数2 复制源数组的位置 //参数3 要复制的目标数组 //参数4 复制到目标数组的位置 //参数5 复制的长度 //Array.Copy(nums1,1, nums2, 1,2); //Console.WriteLine(string.Join("-", nums2));//1 2 3 0//3 indexOf() 查询元素的索引值 int[] nums3 = { 1, 2, 3, 4,3}; Console.WriteLine(Array.IndexOf(nums3,3));//0 Console.WriteLine(Array.LastIndexOf(nums3,3));//4 从后往前匹配 找到满足条件第一个数的索引 //参数3的作用控制查询开始位置 Console.WriteLine(Array.IndexOf(nums3,3,3));//4 //参数4的作用查询的长度 Console.WriteLine(Array.IndexOf(nums3, 3, 3, 2));六、数组的高级方法
Array 会提供一些函数实现按照条件进行查询的方法
静态方法:
Find() 找一个满足条件的元素
FindAll() 找所有满足条件的元素
FindLast() 从后往前找 找满足条件元素
FindIndex() 找索引
FindLastIndex() 从后往前找 找满足条件索引
TrueForAll() 所有元素都满足条件时候 整体才为true
Exists() 查找满足条件的元素 有一个或者多个,整体为true
ForEach() 遍历的方法。非静态方法:实例.方法名()
All方法 如果所有元素都满足条件
Any 只要一个满足条件 整体为true
GetValue 获取元素值
SetValue("郑爽",0) 设置值
GetType() 获取类型
int[] ages = {20, 10, 30,40,50,19,21}; //整型的数组 //Find()的工作原理:循环该数组,并且每次循环调用传递的方法,并且将当前数组,通过参数的形式, // 传递到方法中,如果方法返回了true,则Find直接返回当前这个参数 //Find() 查询满足条件函数的第一个元素,如果匹配函数为true,Find结果为满足条件元素,如果匹配函数为false,Find的结果就是默认值 //参数1:查询的数组 //参数2:是一个匹配函数,这个函数返回值为布尔类型,并且有一个参数为整型, 给参数2传递实参时候 需要定义一个 //函数,在main的下面定义一个函数,把函数直接写在Find第二次参数中 //Find找小于18的第一个元素 Console.WriteLine(Array.Find(ages, FindSmall18)); //10 //Find()函数结果是找到元素 //FindEven()匹配函数 结果true/false //找满足是偶数第一个元素 Console.WriteLine(Array.Find(ages, FindEven));//20 //找奇数的第一个元素 Console.WriteLine(Array.Find(ages, FindOdd));//19 public static bool F2(string v) { return v.Length == 2; } public static void F1(int v) { Console.WriteLine(v+"+++++++++++++++"); } public static bool Find35(int v) { return v%3==0&&v%5==0; } public static bool FindOdd(int v) { return v % 2 != 0; } public static bool FindEven(int v) { return v % 2 == 0; } public static bool FindSmall18(int v) { return v < 18; }int[] ages = {20, 10, 30,40,50,19,21}; //整型的数组 //从后往前找 查找满足条件的第一个 Console.WriteLine(Array.FindLast(ages, Find35)); //30 public static bool Find35(int v) { return v%3==0&&v%5==0; }//FindAll() 查找满足条件所有的元素, //参数1 查询的数组 //参数2 匹配函数 返回值为true/false 参数数组每一个元素类型 int[] arr = Array.FindAll(ages,FindOdd); Console.WriteLine(string.Join("-",arr));//FindIndex()找满足条件元素的索引值 Console.WriteLine(Array.FindIndex(ages, FindEven));//0// FindLastIndex 从后往前找满足条件的第一个索引 Console.WriteLine(Array.FindLastIndex(ages, FindEven));//4//ForEach()遍历的方法 //参数1数组 //参数2 遍历函数,这个函数有一个参数,无返回值 Array.ForEach(ages,F1);//TrueForAll()所有元素都满足条件时候 整体才为true,只要一个不满足条件 ,整体就为false Console.WriteLine(Array.TrueForAll(arr, FindOdd));//Exists()查找满足条件的元素 有一个或者多个。整体为true, Console.WriteLine(Array.Exists(ages,Find35));string[] strs = new string[] { "张三", "李1四" }; Console.WriteLine( strs.Count());//2 ==Length //All方法 如果所有元素都满足条件 则为True, 等同于TrueForAll Console.WriteLine(strs.All(F2));//False //Any 只要一个满足条件 整体为true 等同于Exists() Console.WriteLine( strs.Any(F2));//true Console.WriteLine(strs.GetValue(0)); //获取元素值 strs.SetValue("郑爽",0);//给指定索引值更改元素 Console.WriteLine(strs.GetValue(0)); //int[] 继承于Array Array继承于Object Console.WriteLine(strs.GetType().BaseType.BaseType);//GetType() 获取类型 Console.WriteLine(strs.GetLength(0));//2 指定维度获取长度 public static bool F2(string v) { return v.Length == 2; }七、Lambda表达式
lambda表达式:本质是一个函数,作为另外一个函数参数进行使用,也可以称为是匿名函数(箭头函数)。
表达式语法: (参数类型 a, 参数类型 b,...)=>{ }lambda表达式也可以找一个变量接收,这个变量是类型使用这三种接收,单独写lambda表达式会报错,要么写在高阶函数里面 要么找一个变量接收。
1 Func<> 接收有返回值的函数
2 Predicate<> 接收有返回值为bool类型的函数
3 Action<> 接收无返回值的函数
//Func<int,int ,int> 参数类型 最后一个类型是返回值的类型 //F4 函数名 //(int a, int b) 参数类别 //=> //{函数体} Func<int,int ,int > F4 = (int a, int b) => { return a + b; }; //lambda可以像普通函数去调用 Console.WriteLine(F4(10, 20)); //lambda表达式可以简化 可以把(int a, int b) 类型省掉,如果有个参数小括号不能省掉,可以把return和{}一起省掉。 Func<int, int, int> F5 = (a, b) => a + b; Console.WriteLine(F5(10,30)); //如果只有一个参数的话 可以把小括号省掉 Func<int, int> F6 = a => a;//把lambda表达式应用在高级函数中 // 4.0最终版本 Console.WriteLine(Array.Find(ages, v => v % 2 != 0)); //找奇数的第一个匹配到的元素 //3.0 把lambda表达式定义一个变量 Func<int, bool> F7 = v => v % 2 != 0; //Predicate<> 接收返回值为bool类型,所以不用在定义时候 Predicate<int>写bool类型 Predicate<int> F8 = v => v % 2 != 0; Console.WriteLine(Array.Find(ages, F8)); //无法从Func<> 转成Predicate<> //2.0写法 Console.WriteLine(Array.Find(ages, F9)); //2 bool F9(int v) { return v % 2 == 0; } //1.0 把函数定义在main外面// 定义字符串数组 string[] strings = { "吴亦凡", "罗志祥", "郑爽", "东北雨姐" }; //1.查询第一个长度为2字符串 Console.WriteLine(Array.Find(strings, v => v.Length == 2)); //2.查询第一个长度为2字符串索引 Console.WriteLine(Array.FindIndex(strings,v=>v.Length==2)); // 3.查询第一个以"吴"开头的字符串 Console.WriteLine(Array.Find(strings, v => v.StartsWith("吴"))); //4.查询第一个以"祥"结尾的字符串 Console.WriteLine(Array.Find(strings, v => v.EndsWith("祥"))); //5.查询第一个以"姐"结尾并且长度为4的字符串 Console.WriteLine(Array.Find(strings, v => v.EndsWith("姐") && v.Length==4 )); Console.WriteLine(Array.Find(strings,F10)); //带参数类型string 返回类型bool //string.Join("-", strings.Where(a => a.Length == 3).ToArray()) // where 筛选满足长度为3的元素,返回一个可枚举类型数据 可以通过toArray转成数组类型 string[] ss = strings.Where(a => a.Length == 3).ToArray(); Console.WriteLine(string.Join("-", ss)); public static bool F10(string v) { return v.EndsWith("姐") && v.Length == 4; }总结:
//1 Func<> 有返回值的函数.最后一个函数返回值类型 ,其余的都是参数类型 Func<int, bool> F1 = a => { //a是不是素数 只要 a%2==0 a%3==0 a%(a-1)=0有一个为0 就不是素数 bool isShuSu = true; for (int i = 2; i < a; i++) { if (a%i==0) //不是素数 { isShuSu = false; break; } } return isShuSu; }; Console.WriteLine(F1(8)); int[] ages = {3,5,7}; //All所有元素满足F1条件 整体为true,判断数组元素是不是都是素数 Console.WriteLine(ages.All(F1));//true//2 Action<> 类型的表达式:无返回值函数的 Action<int> F2 = a => { if (a%2==0) { Console.WriteLine(a); } }; F2(3); //把F2使用到Array的方法中 int[] ages1 = { 3, 5, 7,4 }; Array.ForEach(ages1, F2);//3 Predicate<> 接收返回值为bool类型.只能传一个参数 Predicate<int> F3 = (a) => { if (a*a>25) { return true; } return false; }; Console.WriteLine(F3(6)); int[] ages2 = { 3, 5, 7, 4,8 }; int[] arr = Array.FindAll(ages2, F3); Console.WriteLine(string.Join("-",arr));八、自己实现find功能
static void Main(string[] args) { //Array.Find() int[] ages = new int[] { 1, 2, 3 }; // Console.WriteLine(ages[10]); //System.IndexOutOfRangeException: 索引超出了数组界限。 //调用自己的Find方法 //参数1:整型的数组 //参数2:func类型的函数 v => v % 2 == 0 // Console.WriteLine(MyArray.Find(ages, v => v % 2 == 0)); //DivideByZeroException: 尝试除以零。 //int a = 10; //Console.WriteLine(a/0); Console.WriteLine(MyArray.Find(ages, v => v % 2 == 0)); Console.WriteLine(MyArray.Find(ages, v => v % 3 == 0)); } public class MyArray { //arr 就是 int[] ages = new int[] { 1, 2, 3 }; //match 就是 v => v % 2 == 0 函数必须调用 public static int Find(int[] arr,Func<int,bool> match) //match 函数, 必须调用 { if (arr == null) { throw new ArgumentNullException("array"); } if (match==null) { throw new ArgumentNullException("match"); } for (int i = 0; i < arr.Length; i++) //遍历每一个元素,判断元素是否满足match函数 { if (match(arr[i])) // 调用v => v % 2 == 0函数 ,v就是arr【i】 就是每一个元素 { return arr[i];//返回元素本身 } } return 0; //没找到话 返回默认值0 }九、排序
1、冒泡排序
for (int i = 0; i < num1.Length; i++) { // 内循环控制比较次数, 最大次数长度-1-i, 减i的目的把之前找到最值排除掉 // 假设8个数,比较7次 for (int j = 0; j < num1.Length - 1; j++) { if (num1[j] > num1[j + 1]) //num1[j] 前面数;num1[j+1]后面的数 { //交换位置 (num1[j], num1[j + 1]) = (num1[j + 1], num1[j]); } } } Console.WriteLine(string.Join("-", num1));2、选择排序
int[] nums = { 1, 2, 30, 4, 5, 8, 8, 8, 9 }; for (int i = 0; i < nums.Length; i++) { int minIndex = i;// 目前最小值的索引的i, 例如i=0 for (int j = i+1; j < nums.Length; j++) { if (nums[j] < nums[minIndex]) // nums[minIndex] 最小值 ;nums[j]数组里面后面元素 //nums[j]是小值 把小值的索引值赋值给minIndex { minIndex = j; } } if (minIndex!=i) { //交换位置nums[minIndex] (nums[i], nums[minIndex]) = (nums[minIndex], nums[i]); } } Console.WriteLine( string.Join("-",nums));3、sort排序
1.第一种
int[] nums = { 1, 2, 30, 4, 5, 8, 8, 8, 9 }; Array.Sort(nums);// 默认的是升序排序, 从小到大的排序 Array.Reverse(nums);// 颠倒数组的元素的顺序 Console.WriteLine(string.Join("-", nums));2.第二种
Array.Sort(nums, (x, y) => { return x - y; });//升序排序 Console.WriteLine(string.Join("-", nums)); Array.Sort(nums, (x, y) => { return y - x; });//降序排序 Console.WriteLine(string.Join("-", nums));3.第二种
Array.Sort(nums, (x, y) => { if (x < y) return -1; // 如果为负数 x在前面 if (x > y) return 1; // 如果为负数 x在后面 return 0; // 位置不变 }); Console.WriteLine(string.Join("-", nums));