Visual Basic 中的数组
数组是逻辑上彼此相关的一组值(称为元素)。 例如,某个数组包含文法学校每个年级的学生人数;该数组的每个元素是一个年级的学生人数。 类似地,某个数组包含某个学生的班级成绩等级;该数组的每个元素是一个成绩等级。
可以使用单个变量来存储每个数据项。 例如,如果我们的应用程序分析学生的成绩等级,则我们可对每个学生的成绩等级使用单独的变量,例如 englishGrade1
、englishGrade2
等。这种方法存在三个主要限制:
- 在设计时必须确切地知道我们必须处理多少个成绩等级。
- 很难快速处理大量的成绩等级。 而这又会使应用程序更有可能出现严重的 bug。
- 维护很困难。 添加每个新的成绩等级都需要修改、重新编译再重新部署应用程序。
如果使用数组,可以按相同的名称引用这些相关值,并使用一个称作“索引”或“下标”的编号根据单个元素在数组中的位置来标识该元素。 数组的索引范围从 0 开始,到数组中的元素总数减 1。 使用 Visual Basic 语法定义数组的大小时,需指定它的最高索引,而不是数组中的元素总数。 可将数组用作单元,并可以迭代其元素,因而在设计时无需确切知道该数组包含多少元素。
在进行说明之前,请看几个简单的示例:
' Declare a single-dimension array of 5 numbers.
Dim numbers(4) As Integer
' Declare a single-dimension array and set its 4 values.
Dim numbers = New Integer() {1, 2, 4, 8}
' Change the size of an existing array to 16 elements and retain the current values.
ReDim Preserve numbers(15)
' Redefine the size of an existing array and reset the values.
ReDim numbers(15)
' Declare a 6 x 6 multidimensional array.
Dim matrix(5, 5) As Double
' Declare a 4 x 3 multidimensional array and set array element values.
Dim matrix = New Integer(,) {{1, 2, 3}, {2, 3, 4}, {3, 4, 5}, {4, 5, 6}}
' Declare a jagged array
Dim sales()() As Double = New Double(11)() {}
简单数组中的数组元素
让我们创建一个名为 students
的数组来存储文法学校每个年级的学生人数。 这些元素的索引范围为 0 到 6。 使用此数组比声明 7 个变量更方便。
下图显示了 students
数组。 对于数组的每个元素:
元素索引表示年级(索引 0 表示幼儿园)。
元素中包含的值表示每个年级的学生数量。
以下示例包含用于创建和使用数组的 Visual Basic 代码:
Module SimpleArray
Public Sub Main()
' Declare an array with 7 elements.
Dim students(6) As Integer
' Assign values to each element.
students(0) = 23
students(1) = 19
students(2) = 21
students(3) = 17
students(4) = 19
students(5) = 20
students(6) = 22
' Display the value of each element.
For ctr As Integer = 0 To 6
Dim grade As String = If(ctr = 0, "kindergarten", $"grade {ctr}")
Console.WriteLine($"Students in {grade}: {students(ctr)}")
Next
End Sub
End Module
' The example displays the following output:
' Students in kindergarten: 23
' Students in grade 1: 19
' Students in grade 2: 21
' Students in grade 3: 17
' Students in grade 4: 19
' Students in grade 5: 20
' Students in grade 6: 22
该示例执行三项操作:
- 声明包含 7 个元素的
students
数组。 数组声明中的编号6
表示该数组中的最后一个索引;它是数组中的元素数量减 1。 - 将值赋给数组中的每个元素。 可以使用数组名称并在括号中包含单个元素的索引,来访问数组元素。
- 列出数组的每个值。 该示例使用
For
语句按索引编号访问数组的每个元素。
以上示例中的 students
数组是一维数组,因为它使用一个索引。 使用多个索引或下标的数组则称为多维数组。 有关详细信息,请参阅本文的余下部分和 Visual Basic 中的数组维度。
创建数组
可通过多种方式定义数组的大小:
可以在声明数组时指定大小:
' Declare an array with 10 elements. Dim cargoWeights(9) As Double ' Declare a 24 x 2 array. Dim hourlyTemperatures(23, 1) As Integer ' Declare a jagged array with 31 elements. Dim januaryInquiries(30)() As String
可以在创建数组时使用
New
子句提供数组的大小:' Declare an array with 10 elements. Dim cargoWeights() As Double = New Double(9) {} ' Declare a 24 x 2 array. Dim hourlyTemperatures(,) As Integer = New Integer(23, 1) {} ' Declare a jagged array with 31 elements. Dim januaryInquiries()() As String = New String(30)() {}
如果你具有现有数组,你可以通过使用 ReDim
语句来重新定义其大小。 可以指定 ReDim
语句应保留数组中的值,或者可以指定它应该创建一个空数组。 下面的示例演示了用 ReDim
语句来修改现有数组的大小的不同用法。
' Assign a new array size and retain the current values.
ReDim Preserve cargoWeights(20)
' Assign a new array size and retain only the first five values.
ReDim Preserve cargoWeights(4)
' Assign a new array size and discard all current element values.
ReDim cargoWeights(15)
有关详细信息,请参阅 ReDim 语句。
存储数组中的值
你可以通过使用类型 Integer
的索引访问数组中的每个位置。 你可以使用括号内的索引来引用每个数组位置,从而存储和检索数组中的值。 多维数组的索引以逗号 (,) 分隔。 每个数组维度都需要一个索引。
以下示例演示了用于存储和检索数组中的值的一些语句。
Module Example
Public Sub Main()
' Create a 10-element integer array.
Dim numbers(9) As Integer
Dim value As Integer = 2
' Write values to it.
For ctr As Integer = 0 To 9
numbers(ctr) = value
value *= 2
Next
' Read and sum the array values.
Dim sum As Integer
For ctr As Integer = 0 To 9
sum += numbers(ctr)
Next
Console.WriteLine($"The sum of the values is {sum:N0}")
End Sub
End Module
' The example displays the following output:
' The sum of the values is 2,046
使用数组文本填充数组
使用数组文本,可以在创建数组的同时使用一组初始值填充该数组。 数组文本包含用逗号分隔的值列表,这些值被括在括号内 ({}
)。
通过使用数组文本创建数组时,可以提供数组类型或使用类型推理功能来确定数组类型。 以下示例演示了这两个选项。
' Array literals with explicit type definition.
Dim numbers = New Integer() {1, 2, 4, 8}
' Array literals with type inference.
Dim doubles = {1.5, 2, 9.9, 18}
' Array literals with explicit type definition.
Dim articles() As String = { "the", "a", "an" }
' Array literals with explicit widening type definition.
Dim values() As Double = { 1, 2, 3, 4, 5 }
使用类型推理时,数组的类型由文字值列表中的主控类型确定。 主控类型是数组中的所有其他类型可以扩大到的类型。 如果无法确定此唯一类型,基准类型是数组中所有其他类型可以缩小到的唯一类型。 如果无法确定为这两种唯一类型之一,则基准类型是 Object
。 例如,如果提供给数组文本的值的列表包含 Integer
、 Long
和 Double
类型的值,则生成的数组类型是 Double
。 由于 Integer
和 Long
只能扩大到 Double
,因此 Double
是主控类型。 有关详细信息,请参阅 Widening and Narrowing Conversions。
注意
只能对在类型成员中定义为局部变量的数组使用类型推理。 如果不存在显式类型定义,则在类级别使用数组文本定义的数组为 Object[]
类型。 有关详细信息,请参阅局部类型推理。
请注意,尽管所有数组文本的类型为 Integer
,但以上示例将 values
定义为 Double
类型的数组。 之所以能够创建此数组,是因为数组文字中的值可以扩大为 Double
值。
还可以使用嵌套数组文本来创建和填充多维数组。 嵌套数组文本必须具有与生成的数组一致的多个维度。 以下示例使用嵌套数组文本创建二维整数数组。
' Create and populate a 2 x 2 array.
Dim grid1 = {{1, 2}, {3, 4}}
' Create and populate a 2 x 2 array with 3 elements.
Dim grid2(,) = {{1, 2}, {3, 4}, {5, 6}}
使用嵌套数组文本创建和填充数组时,如果嵌套数组文本中的元素数量不匹配,则会发生错误。 如果将数组变量显式声明为具有与数组文本不同的维度数,也会发生错误。
如同创建一维数组时一样,在使用嵌套数组文本创建多维数组时,可以依赖类型推理。 推理出的类型是用于所有嵌套级别的所有数组文本中的所有值的主控类型。 以下示例基于类型为 Integer
和 Double
的值创建一个类型为 Double[,]
的二维数组。
Dim arr = {{1, 2.0}, {3, 4}, {5, 6}, {7, 8}}
有关其他示例,请参阅如何:在 Visual Basic 中初始化数组变量。
循环访问数组
循环访问某个数组时,将从最低索引到最高索引或者从最高索引到最低索引访问数组中的每个元素。 通常使用 For...Next 语句或 For Each...Next 语句来循环访问数组的元素。 如果你不知道数组的上限,可以调用 Array.GetUpperBound 方法获取索引的最大值。 虽然最低索引值几乎始终为 0,但你可以调用 Array.GetLowerBound 方法来获取索引的最低值。
以下示例使用 For...Next
语句循环访问某个一维数组。
Module IterateArray
Public Sub Main()
Dim numbers = {10, 20, 30}
For index = 0 To numbers.GetUpperBound(0)
Console.WriteLine(numbers(index))
Next
End Sub
End Module
' The example displays the following output:
' 10
' 20
' 30
下面的示例使用 For...Next
语句循环访问一个多维数组。 GetUpperBound 方法具有用于指定维度的参数。 GetUpperBound(0)
返回第一个维度的最高索引,GetUpperBound(1)
返回第二个维度的最高索引。
Module IterateArray
Public Sub Main()
Dim numbers = {{1, 2}, {3, 4}, {5, 6}}
For index0 = 0 To numbers.GetUpperBound(0)
For index1 = 0 To numbers.GetUpperBound(1)
Console.Write($"{numbers(index0, index1)} ")
Next
Console.WriteLine()
Next
End Sub
End Module
' The example displays the following output:
' Output
' 1 2
' 3 4
' 5 6
以下示例使用 For Each...Next 语句循环访问某个一维数组和二维数组。
Module IterateWithForEach
Public Sub Main()
' Declare and iterate through a one-dimensional array.
Dim numbers1 = {10, 20, 30}
For Each number In numbers1
Console.WriteLine(number)
Next
Console.WriteLine()
Dim numbers = {{1, 2}, {3, 4}, {5, 6}}
For Each number In numbers
Console.WriteLine(number)
Next
End Sub
End Module
' The example displays the following output:
' 10
' 20
' 30
'
' 1
' 2
' 3
' 4
' 5
' 6
数组大小
数组的大小是数组所有维度的长度的产物。 它表示数组中当前所包含的元素总数。 例如,以下示例声明一个二维数组,其中的每个维度包含四个元素。 从示例的输出中可以看到,该数组的大小为 16(即 (3 + 1) * (3 + 1))。
Module Example
Public Sub Main()
Dim arr(3, 3) As Integer
Console.WriteLine(arr.Length)
End Sub
End Module
' The example displays the following output:
' 16
注意
此处有关数组大小的讨论不适用于交错数组。 有关交错数组和如何确定交错数组大小的信息,请参阅交错数组部分。
可以通过使用 Array.Length 属性查找数组大小。 可以使用 Array.GetLength 方法查找多维数组每个维度的长度。
可以通过为数组变量分配新的数组对象或使用 ReDim
语句来调整数组变量的大小。 以下示例使用 ReDim
语句将包含 100 个元素的数组更改为包含 51 个元素的数组。
Module Example
Public Sub Main()
Dim arr(99) As Integer
Console.WriteLine(arr.Length)
Redim arr(50)
Console.WriteLine(arr.Length)
End Sub
End Module
' The example displays the following output:
' 100
' 51
当处理数组大小时,需要记住几件事情。
备注 | |
---|---|
维度长度 | 每个维度的索引从 0 开始,这意味着它的范围为 0 到其上限。 因此,给定维度的长度比该维度的已声明上限大 1。 |
长度限制 | 数组的每个维度的长度不能超过 Integer 数据类型的最大值,即 Int32.MaxValue 或 (2 ^ 31) - 1。 但是,数组的总大小还受到系统上可用的内存限制。 如果你尝试初始化超出可用内存量的数组,运行时将引发 OutOfMemoryException。 |
大小和元素大小 | 数组的大小独立于其元素的数据类型。 大小始终表示元素总数,而不是元素在内存中占用的字节数。 |
内存消耗 | 做出关于数组如何存储在内存中的假设是不可靠的。 由于不同数据宽度的平台上的存储会有所变化,因此同一数组在 64 位系统上可以占用比在 32 位系统上更多的内存。 具体取决于数组初始化时的系统配置,公共语言运行时 (CLR) 可以尽可能地将存储分配到靠近包元素的地方,或者将它们全部在自然硬件边界上对齐。 此外,数组需要存储开销的控制信息,而且每添加一个维度,这种开销随之增加。 |
数组类型
每个数组都有一个数据类型,该类型不同于该数组的元素的数据类型。 没有一种数据类型能用于所有数组。 相反,数组的数据类型由数组的维度数量或 “排名”,以及数组中元素的数据类型确定。 仅当两个数组变量具有相同的秩且它们的元素具有相同的数据类型时,它们才具有相同的数据类型。 数组的维度长度不会影响数组数据类型。
每个数组都继承自 System.Array 类,并且你可以声明一个类型为 Array
的变量,但不能创建一个类型为 Array
的数组。 例如,尽管以下代码将 arr
变量声明为 Array
类型并调用 Array.CreateInstance 方法来实例化数组,但该数组的类型证明为 Object[]。
Module Example
Public Sub Main()
Dim arr As Array = Array.CreateInstance(GetType(Object), 19)
Console.WriteLine(arr.Length)
Console.WriteLine(arr.GetType().Name)
End Sub
End Module
' The example displays the following output:
' 19
' Object[]
此外,ReDim 语句无法对声明为类型 Array
的变量执行运算。 出于这些原因和类型安全考虑,建议将每个数组声明为特定类型。
你可以通过几种方式了解到数组及其元素的数据类型。
- 可以调用变量上的 GetType 方法来获取表示变量运行时类型的 Type 对象。 Type 对象可在其属性和方法中保存大量信息。
- 可将该变量传递给 TypeName 函数,以获取包含运行时类型名称的
String
。
以下示例调用 GetType
方法和 TypeName
函数来确定数组的类型。 数组类型为 Byte(,)
。 请注意,Type.BaseType 属性还指示字节数组的基类型为 Array 类。
Module Example
Public Sub Main()
Dim bytes(9,9) As Byte
Console.WriteLine($"Type of {nameof(bytes)} array: {bytes.GetType().Name}")
Console.WriteLine($"Base class of {nameof(bytes)}: {bytes.GetType().BaseType.Name}")
Console.WriteLine()
Console.WriteLine($"Type of {nameof(bytes)} array: {TypeName(bytes)}")
End Sub
End Module
' The example displays the following output:
' Type of bytes array: Byte[,]
' Base class of bytes: Array
'
' Type of bytes array: Byte(,)
作为返回值和参数的数组
若要通过 Function
过程返回数组,请将数组数据类型和维度数指定为 Function 语句的返回类型。 在函数内,声明一个具有相同数据类型和维度数的本地数组变量。 在 Return 语句中,添加不带括号的局部数组变量。
若要将作为参数的数组指定到 Sub
或 Function
步骤中,可将此参数定义为具有指定数据类型和维度数量的数组。 在对过程的调用中,传递一个具有相同数据类型和维度数的数组变量。
在以下示例中,GetNumbers
函数返回 Integer()
- 一个 Integer
类型的一维数组。 ShowNumbers
过程接受 Integer()
参数。
Module ReturnValuesAndParams
Public Sub Main()
Dim numbers As Integer() = GetNumbers()
ShowNumbers(numbers)
End Sub
Private Function GetNumbers() As Integer()
Dim numbers As Integer() = {10, 20, 30}
Return numbers
End Function
Private Sub ShowNumbers(numbers As Integer())
For index = 0 To numbers.GetUpperBound(0)
Console.WriteLine($"{numbers(index)} ")
Next
End Sub
End Module
' The example displays the following output:
' 10
' 20
' 30
在以下示例中,GetNumbersMultiDim
函数返回 Integer(,)
- 一个 Integer
类型的二维数组。 ShowNumbersMultiDim
过程接受 Integer(,)
参数。
Module Example
Public Sub Main()
Dim numbers As Integer(,) = GetNumbersMultidim()
ShowNumbersMultidim(numbers)
End Sub
Private Function GetNumbersMultidim() As Integer(,)
Dim numbers As Integer(,) = {{1, 2}, {3, 4}, {5, 6}}
Return numbers
End Function
Private Sub ShowNumbersMultidim(numbers As Integer(,))
For index0 = 0 To numbers.GetUpperBound(0)
For index1 = 0 To numbers.GetUpperBound(1)
Console.Write($"{numbers(index0, index1)} ")
Next
Console.WriteLine()
Next
End Sub
End Module
' The example displays the following output:
' 1 2
' 3 4
' 5 6
交错数组
有时应用程序中的数据结构是二维而不是矩形。 例如,你可能会使用一个数组来存储一个月中每天的高温数据。 该数组的第一个维度表示月份,但第二个维度表示天数,而一个月的天数并不是统一的。 在此类场景下可以使用交错数组(也称为数组的数组)。 交错数组是其元素同样为数组的数组。 交错数组和交错数组中的每个元素都可以具有一个或多个维度。
以下示例使用月份数组,其每个元素是天数的数组。 该示例使用交错数组,因为不同月份的天数不同。 该示例演示如何创建一个交错数组、为其赋值以及检索和显示其值。
Imports System.Globalization
Module JaggedArray
Public Sub Main()
' Declare the jagged array of 12 elements. Each element is an array of Double.
Dim sales(11)() As Double
' Set each element of the sales array to a Double array of the appropriate size.
For month As Integer = 0 To 11
' The number of days in the month determines the appropriate size.
Dim daysInMonth As Integer =
DateTime.DaysInMonth(Year(Now), month + 1)
sales(month) = New Double(daysInMonth - 1) {}
Next
' Store values in each element.
For month As Integer = 0 To 11
For dayOfMonth = 0 To sales(month).GetUpperBound(0)
sales(month)(dayOfMonth) = (month * 100) + dayOfMonth
Next
Next
' Retrieve and display the array values.
Dim monthNames = DateTimeFormatInfo.CurrentInfo.AbbreviatedMonthNames
' Display the month names.
Console.Write(" ")
For ctr = 0 To sales.GetUpperBound(0)
Console.Write($" {monthNames(ctr)} ")
Next
Console.WriteLine()
' Display data for each day in each month.
For dayInMonth = 0 To 30
Console.Write($"{dayInMonth + 1,2}. ")
For monthNumber = 0 To sales.GetUpperBound(0)
If dayInMonth > sales(monthNumber).GetUpperBound(0) Then
Console.Write(" ")
Else
Console.Write($"{sales(monthNumber)(dayInMonth),-5} ")
End If
Next
Console.WriteLine()
Next
End Sub
End Module
' The example displays the following output:
' Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
' 1. 0 100 200 300 400 500 600 700 800 900 1000 1100
' 2. 1 101 201 301 401 501 601 701 801 901 1001 1101
' 3. 2 102 202 302 402 502 602 702 802 902 1002 1102
' 4. 3 103 203 303 403 503 603 703 803 903 1003 1103
' 5. 4 104 204 304 404 504 604 704 804 904 1004 1104
' 6. 5 105 205 305 405 505 605 705 805 905 1005 1105
' 7. 6 106 206 306 406 506 606 706 806 906 1006 1106
' 8. 7 107 207 307 407 507 607 707 807 907 1007 1107
' 9. 8 108 208 308 408 508 608 708 808 908 1008 1108
' 10. 9 109 209 309 409 509 609 709 809 909 1009 1109
' 11. 10 110 210 310 410 510 610 710 810 910 1010 1110
' 12. 11 111 211 311 411 511 611 711 811 911 1011 1111
' 13. 12 112 212 312 412 512 612 712 812 912 1012 1112
' 14. 13 113 213 313 413 513 613 713 813 913 1013 1113
' 15. 14 114 214 314 414 514 614 714 814 914 1014 1114
' 16. 15 115 215 315 415 515 615 715 815 915 1015 1115
' 17. 16 116 216 316 416 516 616 716 816 916 1016 1116
' 18. 17 117 217 317 417 517 617 717 817 917 1017 1117
' 19. 18 118 218 318 418 518 618 718 818 918 1018 1118
' 20. 19 119 219 319 419 519 619 719 819 919 1019 1119
' 21. 20 120 220 320 420 520 620 720 820 920 1020 1120
' 22. 21 121 221 321 421 521 621 721 821 921 1021 1121
' 23. 22 122 222 322 422 522 622 722 822 922 1022 1122
' 24. 23 123 223 323 423 523 623 723 823 923 1023 1123
' 25. 24 124 224 324 424 524 624 724 824 924 1024 1124
' 26. 25 125 225 325 425 525 625 725 825 925 1025 1125
' 27. 26 126 226 326 426 526 626 726 826 926 1026 1126
' 28. 27 127 227 327 427 527 627 727 827 927 1027 1127
' 29. 28 228 328 428 528 628 728 828 928 1028 1128
' 30. 29 229 329 429 529 629 729 829 929 1029 1129
' 31. 30 230 430 630 730 930 1130
以上示例使用 For...Next
循环按照每个元素为交错数组赋值。 也可以使用嵌套数组文本为交错数组的元素赋值。 但是,尝试使用嵌套数组文本(例如 Dim valuesjagged = {{1, 2}, {2, 3, 4}}
)会生成编译器错误 BC30568。 若要更正该错误,请将内部数组文本括在括号中。 括号强制计算数组文本表达式,并将生成的值与外部数组文本一起使用,如以下示例所示。
Module Example
Public Sub Main()
Dim values1d = { 1, 2, 3 }
Dim values2d = {{1, 2}, {2, 3}, {3, 4}}
Dim valuesjagged = {({1, 2}), ({2, 3, 4})}
End Sub
End Module
交错数组是其元素包含数组的一维数组。 因此,Array.Length 属性和 Array.GetLength(0)
方法返回一维数组中的元素数,而 Array.GetLength(1)
引发 IndexOutOfRangeException,因为交错数组不是多维数组。 可以通过检索每个子数组的 Array.Length 属性值,来确定每个子数组中的元素数。 以下示例演示如何确定交错数组中的元素数。
Module Example
Public Sub Main()
Dim jagged = { ({1, 2}), ({2, 3, 4}), ({5, 6}), ({7, 8, 9, 10}) }
Console.WriteLine($"The value of jagged.Length: {jagged.Length}.")
Dim total = jagged.Length
For ctr As Integer = 0 To jagged.GetUpperBound(0)
Console.WriteLine($"Element {ctr + 1} has {jagged(ctr).Length} elements.")
total += jagged(ctr).Length
Next
Console.WriteLine($"The total number of elements in the jagged array: {total}")
End Sub
End Module
' The example displays the following output:
' The value of jagged.Length: 4.
' Element 1 has 2 elements.
' Element 2 has 3 elements.
' Element 3 has 2 elements.
' Element 4 has 4 elements.
' The total number of elements in the jagged array: 15
零长度数组
Visual Basic 区分未初始化的数组(其值为 Nothing
的数组)和零长度数组,后者也称为空数组(不包含元素的数组)。未初始化的数组是指尚未对其进行维度计算或已分配任何值的数组。 例如:
Dim arr() As String
零长度数组是使用维度 -1 声明的。 例如:
Dim arrZ(-1) As String
在下列情况下,你可能需要创建一个零长度数组:
为避免出现 NullReferenceException 异常风险,代码必须访问 Array 类的成员(例如 Length 或 Rank),或调用 UBound 之类的 Visual Basic 函数。
无需出于特殊情况检查
Nothing
,这样可以保持代码的简单性。你的代码与应用程序编程接口 (API) 交互,该接口要求你将一个零长度数组传递到一个或多个过程,或将一个零长度数组返回到一个或多个过程。
拆分数组
在某些情况下,你可能需要将单个数组拆分为多个数组。 这涉及到确定该数组的一个或多个拆分点,然后将该数组拆分为两个或更多个单独的数组。
备注
本部分不讨论如何基于某个分隔符将单个字符串拆分为字符串数组。 有关拆分字符串的信息,请参阅 String.Split 方法。
拆分数组的最常见条件是:
数组中的元素数。 例如,你可能想要将包含超过指定数量的元素的某个数组拆分为大致相等的多个数组。 为此,可以使用 Array.Length 或 Array.GetLength 方法返回的值。
用作分隔符的元素的值,该分隔符指示数组的拆分位置。 可以通过调用 Array.FindIndex 和 Array.FindLastIndex 方法来搜索特定的值。
确定了作为数组拆分位置的一个或多个索引后,可以通过调用 Array.Copy 方法来创建单独的数组。
以下示例将一个数组拆分为大小大致相等的两个数组。 (如果数组元素的总数是奇数,则第一个数组的元素比第二个多 1 个。)
Module Example
Public Sub Main()
' Create an array of 100 elements.
Dim arr(99) As Integer
' Populate the array.
Dim rnd As new Random()
For ctr = 0 To arr.GetUpperBound(0)
arr(ctr) = rnd.Next()
Next
' Determine how many elements should be in each array.
Dim divisor = 2
Dim remainder As Integer
Dim boundary = Math.DivRem(arr.GetLength(0), divisor, remainder)
' Copy the array.
Dim arr1(boundary - 1 + remainder), arr2(boundary - 1) as Integer
Array.Copy(arr, 0, arr1, 0, boundary + remainder)
Array.Copy(arr, boundary + remainder, arr2, 0, arr.Length - boundary)
End Sub
End Module
以下示例根据是否存在值为“zzz”的元素(用作数组分隔符),将某个字符串数组拆分为两个数组。 新数组不包括含有分隔符的元素。
Module Example
Public Sub Main()
Dim rnd As New Random()
' Create an array of 100 elements.
Dim arr(99) As String
' Populate each element with an arbitrary ASCII character.
For ctr = 0 To arr.GetUpperBound(0)
arr(ctr) = ChrW(Rnd.Next(&h21, &h7F))
Next
' Get a random number that will represent the point to insert the delimiter.
arr(rnd.Next(0, arr.GetUpperBound(0))) = "zzz"
' Find the delimiter.
Dim location = Array.FindIndex(arr, Function(x) x = "zzz")
' Create the arrays.
Dim arr1(location - 1) As String
Dim arr2(arr.GetUpperBound(0) - location - 1) As String
' Populate the two arrays.
Array.Copy(arr, 0, arr1, 0, location)
Array.Copy(arr, location + 1, arr2, 0, arr.GetUpperBound(0) - location)
End Sub
End Module
联接数组
还可以将多个数组合并成一个更大的数组。 为此,也可以使用 Array.Copy 方法。
注意
本部分不讨论如何将字符串数组联接成单个字符串。 有关联接字符串数组的信息,请参阅 String.Join 方法。
在将每个数组的元素复制到新数组之前,必须首先确保已初始化该新数组,使其有足够大的空间容纳这些元素。 可以通过两种方法执行此操作:
- 在将新元素添加到数组之前,请使用
ReDim Preserve
语句动态扩展该数组。 这是最简单的方法,但在复制大数组时,这可能会导致性能降低和消耗过多的内存。 - 计算新的大数组所需的元素总数,然后将每个源数组的元素添加到其中。
以下示例使用第二种方法将四个数组(每个数组包含 10 个元素)添加到单个数组中。
Imports System.Collections.Generic
Imports System.Threading.Tasks
Module Example
Public Sub Main()
Dim tasks As New List(Of Task(Of Integer()))
' Generate four arrays.
For ctr = 0 To 3
Dim value = ctr
tasks.Add(Task.Run(Function()
Dim arr(9) As Integer
For ndx = 0 To arr.GetUpperBound(0)
arr(ndx) = value
Next
Return arr
End Function))
Next
Task.WaitAll(tasks.ToArray())
' Compute the number of elements in all arrays.
Dim elements = 0
For Each task In tasks
elements += task.Result.Length
Next
Dim newArray(elements - 1) As Integer
Dim index = 0
For Each task In tasks
Dim n = task.Result.Length
Array.Copy(task.Result, 0, newArray, index, n)
index += n
Next
Console.WriteLine($"The new array has {newArray.Length} elements.")
End Sub
End Module
' The example displays the following output:
' The new array has 40 elements.
由于在本例中源数组都很小,因此我们还可以在将每个新数组的元素添加到目标数组时动态扩展该数组。 以下示例执行该操作。
Imports System.Collections.Generic
Imports System.Threading.Tasks
Module Example
Public Sub Main()
Dim tasks As New List(Of Task(Of Integer()))
' Generate four arrays.
For ctr = 0 To 3
Dim value = ctr
tasks.Add(Task.Run(Function()
Dim arr(9) As Integer
For ndx = 0 To arr.GetUpperBound(0)
arr(ndx) = value
Next
Return arr
End Function))
Next
Task.WaitAll(tasks.ToArray())
' Dimension the target array and copy each element of each source array to it.
Dim newArray() As Integer = {}
' Define the next position to copy to in newArray.
Dim index = 0
For Each task In tasks
Dim n = Task.Result.Length
ReDim Preserve newArray(newArray.GetUpperBound(0) + n)
Array.Copy(task.Result, 0, newArray, index, n)
index += n
Next
Console.WriteLine($"The new array has {newArray.Length} elements.")
End Sub
End Module
' The example displays the following output:
' The new array has 40 elements.
可替代数组的集合
数组最适用于创建和使用固定数量的强类型化对象。 集合提供更灵活的方式来使用对象组。 与需要使用 ReDim
语句显式更改数组大小的数组不同,集合可以随着应用程序需求的变化而动态增长和缩小。
当你使用 ReDim
调整数组的维度时,Visual Basic 会创建一个新数组并释放前一个数组。 这需要执行时间。 因此,如果你处理的项数频繁变化,或者无法预测所需的最大项数,则使用集合通常可以获得更好的性能。
对于某些集合,你可以为放入集合中的任何对象分配一个密钥,这样你便可以使用该密钥快速检索此对象。
如果集合中只包含一种数据类型的元素,则可以使用 System.Collections.Generic 命名空间中的一个类。 泛型集合强制类型安全,因此无法向其添加任何其他数据类型。
有关集合的详细信息,请参阅集合。
相关主题
术语 | 定义 |
---|---|
Array Dimensions in Visual Basic | 在数组中解释级别和维度。 |
如何:在 Visual Basic 中初始化数组变量 | 说明如何用初始值填充数组。 |
如何:在 Visual Basic 中对数组进行排序 | 显示如何按字母先后顺序对数组元素进行排序。 |
如何:将一个数组赋给另一个数组 | 说明将数组分配到另一个数组变量的规则和步骤。 |
数组疑难解答 | 讨论在使用数组时出现的一些常见问题。 |