【c#基础】7.数组
目录
一、一维数组
(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));
更多推荐



所有评论(0)