目录

一、一维数组

二、多维数组

三、交错数组

四、存储引用类型

五、数组的属性和方法

六、数组的高级方法

七、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));

更多推荐