Visual Basic 中的陣列
陣列是一組稱為元素的值,這些元素在邏輯上彼此相關。 例如,陣列可能包含文法學校中每個年級的學生數目;陣列的每個元素是單一年級的學生數目。 同樣地,陣列可能包含班級的學生年級;陣列的每個元素都是單一年級。
您可以使用個別變數來儲存每個資料項目。 例如,如果我們的應用程式分析學生成績,我們可以針對每個學生的年級使用不同的變數,例如 englishGrade1
、englishGrade2
等。此方法有三個主要限制:
- 我們必須在設計階段知道我們必須處理的年級數目。
- 處理大量年級很快會變得龐大。 如此一來,應用程式便更可能有嚴重的錯誤 (bug)。
- 難以維護。 我們增加的每個新年級都需要修改、重新編譯和重新部署應用程式。
藉由使用陣列,您可以以相同名稱參照這些相關值,並使用稱為索引或下標的數字,以根據其在陣列中的位置來識別個別元素。 陣列的索引範圍從 0 到陣列中元素的總數減一。 使用 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。 使用此陣列較宣告七個不同的變數來得簡單。
下圖顯示 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
範例會執行三件事:
- 它會宣告具有七個元素的
students
陣列。 陣列宣告中的數字6
表示陣列中的最後一個索引;其小於陣列中的元素數目。 - 它會將值指派給陣列中的每個元素。 陣列元素是使用陣列名稱來存取,並在括弧中包含個別元素的索引。
- 它會列出陣列的每個值。 範例會使用
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
陣列大小
陣列大小為其所有維度長度之乘積。 它代表目前包含於陣列中的項目總數。 例如,下列範例會宣告每個維度中有四個元素的 2 維陣列。 如範例輸出所示,陣列的大小為 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 到它的上限為止。 因此,指定維度的長度會比該維度宣告的上限多一。 |
長度限制 | 陣列的每個維度長度都受限於 Integer 資料型別的最大值,也就是 Int32.MaxValue 或 (2 ^ 31) - 1。 然而,陣列之總大小也同時受限於系統可用的記憶體。 若您嘗試初始化超過可用記憶體的陣列,執行階段將擲回 OutOfMemoryException。 |
大小及項目大小 | 陣列大小與其項目的資料類型無關。 大小一律是指元素的總數,而不是它們於記憶體中所佔的位元組。 |
記憶體使用量 | 對陣列在記憶體中的儲存方式做任何假設都是不安全的。 儲存體會因不同資料寬度的平台而有差異,所以相同陣列於 64 位元系統上所佔記憶體將較 32 位元系統來的多。 當您初始化陣列時,隨著系統組態不同,通用語言執行平台 (CLR) 會指派儲存體盡可能將項目存放在一起,或是根據實體硬體界限全部加以調整。 同時,陣列需要耗用儲存體以供其控制資訊使用,此消耗量會隨著維度增加而增加。 |
陣列型別
每個陣列都具有其資料型別,其與陣列元素的資料型別不同。 沒有任何單一的資料類型適用於所有的陣列。 陣列的類型反而是由陣列的維度數目,或稱為 「順位」(rank) 以及陣列項目的資料類型所決定。 只要兩個陣列變數具有相同的順位且其元素具有相同的資料型別,便具有相同資料型別。 陣列中維度的長度不會影響陣列的資料型別。
每個陣列都繼承自 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),或者呼叫 Visual Basic 函式 (例如 UBound)。
您希望不需檢查
Nothing
作為特殊情況,讓程式碼更簡單。程式碼會與應用程式開發介面互動,這個介面會要求您傳遞長度為零的陣列給一個或多個程序,或從一個或多個程序傳回長度為零的陣列。
分割陣列
在某些情況下,您可能需要將單一陣列分割成多個陣列。 這牽涉到識別要分割陣列的一或多個點,然後將陣列插入兩或多個不同的陣列。
注意
本節不會討論根據一些分隔符號將單一字串分割成字串陣列。 如需分割字串的相關資訊,請參閱 String.Split 方法。
分割陣列最常見的準則如下:
陣列中的項目數。 例如,您可能想要將超過指定元素數目的陣列分割成大約相等的部分。 為此,您可以使用 Array.Length 或 Array.GetLength 方法傳回的值。
做為分隔符號的元素值,會指出應該分割陣列的位置。 您可以呼叫 Array.FindIndex 和 Array.FindLastIndex 方法來搜尋特定值。
一旦決定應該分割陣列的索引或索引之後,就可以呼叫 Array.Copy 方法來建立個別陣列。
下列範例會將陣列分割成大小大約相等的兩個陣列。 (如果陣列元素的總數是奇數,則第一個陣列的元素數量會較第二個陣列多一個。)
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 中排序陣列 | 示範如何依字母順序排列陣列中的項目。 |
如何:指派一個陣列至另一個陣列 | 描述將陣列指派給另一個陣列變數的規則和步驟。 |
針對陣列進行疑難排解 | 討論在使用陣列時會引發的一些常見問題。 |