• C#&&数组


    数组是最常用的数据结构,几乎在所有的编程语言中都会出现。在C#里用数组的话需要建立一个System.Array类型的对象,它是所有数组的抽象基类。
    Array类提供了一组排序和查找的方法
    另一个可以建立数组的替代品是ArrayList,ArrayList是可以按需要动态增长的数组。
    在不能确定一个数组的大小的情况下,或在程序的生命周期内数组的大下需要改变时,ArrayList是个好的选择。
    还有包括拷贝,克隆的内容,比较是否相等以及用Array和ArrayList的静态方法。

    声明和初使化数组
    数组声明时用下面的格式:

    type[] array_name;
    type就是数据类型,比如
    string[] names;

    第二行需要实例化这个数组(因为是System.Array类型)并指定数组的大小。代码如下:
    names = new string[10];
    这样就为10个字符串分配了内存。

    也可以两句合在一起写:

    string[] names = new string[10];
    有时候你想把声明,实例化,指定数据三个步骤同时进行,那就这样子:
    int[] numbers = new int[] {1,2,3,4,5};
    这一串数字,叫做初使化列表,用花括号括起来,每个元素用逗号隔开。
    当用这种方式声明数组时,不用指定数组大小,编译器会自动根据初使化列表的个数来指定。

    设定和存取数组元素
    数组元素的存储既可以直接存储,也可以调用SetValue方法,直接存储方法需要用索引指定数组内的位置,向下面这样:

    Names[2] = "Raymond";
    Sales[19] = 23123;
    SetValue方法提供了一个更面向对象的做法去设置数组元素的值,此方法有两个参数,一个是索引数,另一个是值。
    names.SetValue[2, "Raymond"];
    sales.SetValue[19, 23123];
    数组元素的取出既可以直接取得,也可以调用GetValue方法,GetValue用一个简单的参数:索引数

    myName = names[2];
    monthSales = sales.GetValue[19];

    通过循环去取得数组内的每个元素是很常见的。程序员写循环时会经常犯一个错误:就是写死了循环的上限或调用取得上限的方法。
    错误主要是因为数组的上限是动态的
    for (int i = 0; i <= sales.GetUpperBound(0); i++)
    totalSales = totalSales + sales[i];
    检索数组元数据的方法和属性:
    Length:返回数组元素的所有个数。
    GetLength:返回数组元素一维内的个数。
    Rank:返回维数
    GetType:返回当前数组实例的类型

    Length方法在统计多维数组内元素的个数时很有用。要不然就用GetUpperBound方法+1取这个值
    因为Length方法返回的是数组内所有元素的个数,GetLength方法返回的是一维内数组的个数。
    Rank属性可以在运行时改变数组的大小而不用担心丢失数据,这个在章节后面详细讨论。
    GetType方法是当你确定不了数组类型时用来判定数据类型的方法,比如数组是入参。
    下面的代码,会创建一个Type类型的变量,允许我们调用一个类方法:IsArray()来判定这个对象是否是数组,
    如果是数组的话,那么就返回数组的数据类型
    int[] numbers;
    numbers = new int[] {0,1,2,3,4};
    Type arrayType = numbers.GetType();
    if (arrayType.IsArray)
    Console.WriteLine("The array type is: {0}", arrayType);
    else
    Console.WriteLine("Not an array");
    Console.Read();

    GetType方法不仅返回数组的类型,也告诉我们数组其实是一个对象,下面是输出的代码:
    The array type is: System.Int32[]
    方括号说明这个对象是个数组,也注意一下当显示数组类型时我们使用的格式。
    知道了这个,我们不能转换把这个类型转换成string去连接剩下的字符串

    多维数组
    目前我们的讨论都限于一维数组,C#里,可以用最多32维的数组,虽然3维以上的数组就不常用了(还混乱的很)。
    多维数组是用指定了每维上限的数组声明的,2维的声明:
    int[,] grades = new int[4,5];
    声明一个4行5列的数组,2维数组一般用来模拟矩阵。
    你也可以声明一个不指定每一维的上限的多维数组,用逗号分开就行了。
    举个例子:
    double[,] Sales;
    声明一个2维数组,
    double[,,] sales;
    声明一个3维数组,当你声明数组不指定某维的上限时,用的时候要指定

    多维数组也可以用初使化列表,看下面的代码:
    Int[,] grades = new int[,] {{1, 82, 74, 89, 100},
    {2, 93, 96, 85, 86},
    {3, 83, 72, 95, 89},
    {4, 91, 98, 79, 88}}
    首先,注意数组的上限是没有指定的,当用初使化列表来初使化一个数组时,
    不能指定该数组的上限。编译器会通过初使化列表计算每一维的上限。
    初使化列表本身是一对花括号,每一行,每一个元素都用逗号分开。

    取得多数组的元素和一维是差不多的,传统技术是这样的:

    grade = Grades[2,2];
    Grades[2,2] = 99
    或者也可以用GetValue方法
    grade = Grades.GetValue[0,2];

    但不能用SetValue方法来设置多维数组的数据,因为这个方法只有两个参数。

    在多维数组里计算所有元素是很常见的操作,虽然常常时是基于某一行或某一列的数据。
    用Grades这个数组,如果数组的每一行是一条学生记录,我们可以计算年级里每个学生的平均分:

    (代码如下)

    int[,] grades = new int[,] {{1, 82, 74, 89, 100},
                  {2, 93, 96, 85, 86},
                  {3, 83, 72, 95, 89},
                  {4, 91, 98, 79, 88}};
    int last_grade = grades.GetUpperBound(1);
    double average = 0.0;
    int total;
    int last_student = grades.GetUpperBound(0);
    for(int row = 0; row <= last_student; row++) {
        total = 0;
    for (int col = 0; col <= last_grade; col++)
          total += grades[row, col];
    average = total / last_grade;
    Console.WriteLine("Average: " + average);
      }
    }

    参数数组
    很多方法的定义需要提供好几个参数,但是有时候你想写一个参数个数可选的方法。
    你可以声明一个参数数组。参数数组是用关键字ParamArray定义参数列表的。
    下面这个方法允许任意个数的参数,返回值是参数的个数。static int sumNums(params int[] nums) {

    int sum = 0;
    for(int i = 0; i <= nums.GetUpperBound(0); i++)
    sum += nums[i];
    return sum;
    }

    这个方法可以被以下代码调用:

    total = sumNums(1, 2, 3);
    total = sumNums(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
    当你用参数数组定义一个方法时,参数数组必须放在此方法所有参数的最后,
    这样编译器可以正确处理参数,否则,编译器不知道参数个数什么时候结束。

    不规则数组
    当你创建一个多维数组时,你一直创建的是每一行的元素个数相同的结构。打个比方,你看下面的代码:

    int sales[,] = new int[12,30];//销售员每个月每天的情况
    假设每行(每月)有同样的元素个数(天数),而实际上有的月31天,有的30天,有的29.
    这样数据就有空位置,在这个数组里问题倒不大,但是一旦数据量大了以后就很浪费了

    解决问题的方法是使用一个不规则数组来代替二维数组。
    不规则数组是一个数组的每一行也是数组的数组。不规则数组的每一维是一维数组,叫它“不规则”是因为每一行的个数不同。
    不规则数组的样子可能不是一个矩形,但是有不规则的边。
    不规则数组用数组名后的两对括号声明。第一对括号指定行数,第二对是留空的。
    int[][] jagged = new int[12][];

    这句代码看上去有点怪,但是分开来理解就明白了。这个不规则数组有12个元素。
    每个元素也是一个数组。初使化列表其实就是为了初使化每一行数据,说明每一行元素是有12个元素的数据,每个元素都初使成默认值。
    一旦不规则数组声明,每一行的元素就可以指定指了,下面的代码就是设置值的:
    jagged[0][0] = 23;
    jagged[0][1] = 13;
    . . .
    jagged[7][5] = 45;
    第一对括号指明行号,第二对括号指明这一行的某一个元素。
    第一句取第一行的第一个元素,第二句取第一行的第二个元素。
    第三句取第6行的第8个元素。

    一个用不规则数组的例子,下面的程序创建一个叫做sales的数组,循环用来计算这两个月每周的平均销售情况。

    using System;
    class class1 {
    static void Main[] {
    int[] Jan = new int[31];
    int[] Feb = new int[29];
    int[][] sales = new int{Jan, Feb};
    int month, day, total;
    double average = 0.0;
    sales[0][0] = 41;
    sales[0][1] = 30;
    sales[0][0] = 41;
    sales[0][1] = 30;
    sales[0][2] = 23;
    sales[0][3] = 34;
    sales[0][4] = 28;
    sales[0][5] = 35;
    sales[0][6] = 45;
    sales[1][0] = 35;
    sales[1][1] = 37;
    sales[1][2] = 32;
    sales[1][3] = 26;
    sales[1][4] = 45;
    sales[1][5] = 38;
    sales[1][6] = 42;
    for(month = 0; month <= 1; month++) {
    total = 0;
    for(day = 0; day <= 6; day++)
    total += sales[month][day];
    average = total / 7;
    Console.WriteLine("Average sales for month: " +
    month + ": " + average);
    }
    }
    }

    ArrayList类
    在不知道数组大小的情况或运行时数组大小要改变的情况下,静态数组就不是那么有用了。
    一个解决方是用一个空间不够用时可以自增长的数组类型,这个数组就是ArrayList,它也是System.Collections里的一部分。
    ArrayList类的对象有一个Capacity属性用来存储数组大小,初使值是16,当数组的元素接近16个时,Capacity会加16,
    当然同时数组空间也变大了。需要用ArrayList的情况是这样的:数组可能会变大或变小时,它比在标准数组里用ReDim更高效。
    这个第一章也说过,ArrayList存储的是对象类型,如果需要强类型数组,你应该用标准数组或其他数据结构。 

    以下是些常用的方法或属性:
     Add(): 向ArrayList添加一个元素.
     AddRange(): 向ArrayList添加一组元素.
     Capacity: 存储ArrayList可以容纳元素的个数
     Clear(): 从ArrayList中移除一个元素.
     Contains(): 判断是否有指定的元素存在于ArrayList.
     CopyTo(): 复制ArrayList或是ArrayList的一部分到一个Array类.
     Count: 返回ArrayList内的元素个数.
     GetEnumerator(): 返回一个ArrayList的迭代器.
     GetRange(): 返回ArrayList的一个子集.
     IndexOf(): 返回第一个发现的指定元素的索引.
     Insert(): 向ArrayList的指定位置插入一个元素.
     InsertRange(): 向ArrayList的指定位置插入一组元素
     Item(): 设置或取得某个指定位置的值.
     Remove(): 移除第一个发现的指定元素.
     RemoveAt(): 移除指定位置的元素.
     Reverse(): 逆序.
     Sort(): 按字母排序.
     ToArray(): 复制所有元素到一个Array类.
     TrimToSize(): 将Capacity值设置成与数组元素个数相等的值.

    使用ArrayList类
    ArrayList不像标准的数组。一般来说,添加元素用Add(),除非在特定位置添加,那就用Insert()。
    这里,我们测试一下怎么使用ArrayList的其他方法。
    首先声明一个对象ArrayList grades = new ArrayList();
    注意这里用了构造函数,如果ArrayList没有用构造函数,这个ArrayList对象就不能使用。
    用Add方法添加元素,这个方法只有一个参数,就是要添加到ArrayList的对象。
    Add方法有返回值,返回的插入的位置,只是很少用而已。下面是例子:
    grades.Add(100);
    grades.Add(84);
    int position;
    position = grades.Add(77);
    Console.WriteLine("The grade 77 was added at position:
    " + position);

    ArrayList对象可以用Foreach来遍历,ArrayList有一个内建的枚举器
    int total = 0;
    double average = 0.0;
    foreach (Object grade in grades)
    total += (int)grade;
    average = total / grades.Count;
    Console.WriteLine("The average grade is: " + average);

    如果你要添加元素到特定位置,用Insert方法,有两个参数,位置和值
    grades.Insert(1, 99);
    grades.Insert(3, 80);

    查看ArrayList当前的容量可以用Capacity属性,看数组个数可以用Count属性
    Console.WriteLine("The current capacity of grades is:
    " + grades.Capacity);
    Console.WriteLine("The number of grades in grades is:
    " + grades.Count);

    这里有些其他的方法移除元素,如果你知道要移除的元素,但不知道位置,用Remove方法,只有一个参数,就是这个你要移除的对象。
    如果这个对象存在于ArrayList中,会被移除,否则,什么都不做。就像是以下的代码。
    if (grades.Contains(54))
    grades.Remove(54)
    else
    Console.Write("Object not in ArrayList.");

    如果知道要移除的对象的位置,用RemoveAt方法,这个方法有一个参数:对象的索引。
    如果传入无效的索引则会异常。
    grades.RemoveAt(2);

    取得一个对象的索引用IndexOf方法,有一个参数,就是这个对象。返回这个对象的索引。如果不存在,返回-1
    int pos;
    pos = grades.IndexOf(70);
    grades.RemoveAt(pos);

    如果要添加对象集合的话,这组对象必须派生自ICollection,意思是说,这组对象可以存在于数组,Collection或者ArrayList里。
    这里有两个不同的方法去添加一组对象到ArrayList。AddRange和InsertRange,AddRange添加元素到末尾,InsertRange方法添加到指定位置。

    (代码如下)

    结果如下

    前面两个名字在ArrayList的开头是因为指定的索引是0.最后的那些名字在末尾是因为用的AaddRange。
    还有两个常用的方法是ToArray和GetRange方法。GetRange方法返回ArrayList里的一组对象做为新的ArrayList。
    ToArray方法复制所有元素到一个array元素

    GetRange方法有两个参数:开始的索引和要取得的元素个数。
    GetRange方法没有破坏性,只是取复本而已。下面是例子代码

    ArrayList someNames = new ArrayList();
    someNames = names.GetRange(2,4);
    Console.WriteLine("someNames sub-ArrayList: ");
    foreach (Object name in someNames)
    Console.WriteLine(name);

    总结:

    数组是最常用的数据结构。几乎所有的编程语言都内置了数组类型。
    很多应用程序里,数组是最简单最有效的数据结构,数组是很有用的。
    .net有一个新的数组类型叫做ArrayList,基本上和数组差不多,但更强的是它可以重新设置容量。
    ArrayList还有一些很有用的方法,比如插入,删除,以及查找。
    因为C#不允许程序员像VB.net那样动态变更数组的大小,ArrayList在不知道数组大小的情况下是很有用的数据结构。

  • 相关阅读:
    2021 2月 构建之法读书笔记
    2021 2 7 体温登记App开发总结
    2021 2 3android开发学习笔记 8
    2021 2 2 android开发学习笔记 7
    2021 1月 梦断代码读后感
    2021 2 1 android开发学习笔记 6
    2021 1 31 Android开发 学习笔记 5
    2021 1 28 android开发学习笔记 4
    2021 1 27 android开发学习笔记3
    Java作业(一)
  • 原文地址:https://www.cnblogs.com/tjuxiepeng/p/4461338.html
Copyright © 2020-2023  润新知