# 陣列Arrays

API 參考連結將帶您前往 MSDN。The API reference link will take you to MSDN. docs.microsoft.com API 參考不完整。The docs.microsoft.com API reference is not complete.

## 建立陣列Creating Arrays

let array1 = [| 1; 2; 3 |]


let array1 =
[|
1
2
3
|]


// Causes an error.
// let array2 = [| 1.0; 2; 3 |]


let array3 = [| for i in 1 .. 10 -> i * i |]


let arrayOfTenZeroes : int array = Array.zeroCreate 10


## 存取元素Accessing Elements

array1.[0]


// Accesses elements from 0 to 2.

array1.[0..2]

// Accesses elements from the beginning of the array to 2.

array1.[..2]

// Accesses elements from 2 to the end of the array.

array1.[2..]


## 陣列類型和模組Array Types and Modules

Library 模組Microsoft.FSharp.Collections.Array支援一維陣列上的作業。The library module Microsoft.FSharp.Collections.Array supports operations on one-dimensional arrays. 模組Array2DArray3D和包含的函式，分別支援兩個、三個和四個維度之陣列的作業。Array4DThe modules Array2D, Array3D, and Array4D contain functions that support operations on arrays of two, three, and four dimensions, respectively. 您可以使用System.Array，建立大於四的次序陣列。You can create arrays of rank greater than four by using System.Array.

### 簡單函式Simple Functions

Array.get取得元素。Array.get gets an element. Array.length提供陣列的長度。Array.length gives the length of an array. Array.set將元素設定為指定的值。Array.set sets an element to a specified value. 下列程式碼範例說明如何使用這些函數。The following code example illustrates the use of these functions.

let array1 = Array.create 10 ""
for i in 0 .. array1.Length - 1 do
Array.set array1 i (i.ToString())
for i in 0 .. array1.Length - 1 do
printf "%s " (Array.get array1 i)


0 1 2 3 4 5 6 7 8 9


### 建立陣列的函式Functions That Create Arrays

let myEmptyArray = Array.empty
printfn "Length of empty array: %d" myEmptyArray.Length

printfn "Array of floats set to 5.0: %A" (Array.create 10 5.0)

printfn "Array of squares: %A" (Array.init 10 (fun index -> index * index))

let (myZeroArray : float array) = Array.zeroCreate 10


Length of empty array: 0
Area of floats set to 5.0: [|5.0; 5.0; 5.0; 5.0; 5.0; 5.0; 5.0; 5.0; 5.0; 5.0|]
Array of squares: [|0; 1; 4; 9; 16; 25; 36; 49; 64; 81|]


Array.copy建立新的陣列，其中包含從現有陣列複製的元素。Array.copy creates a new array that contains elements that are copied from an existing array. 請注意，複製是淺層複製，這表示如果元素類型是參考型別，則只會複製參考，而不會複製基礎物件。Note that the copy is a shallow copy, which means that if the element type is a reference type, only the reference is copied, not the underlying object. 下列程式碼範例會說明這點。The following code example illustrates this.

open System.Text

let firstArray : StringBuilder array = Array.init 3 (fun index -> new StringBuilder(""))
let secondArray = Array.copy firstArray
// Reset an element of the first array to a new value.
firstArray.[0] <- new StringBuilder("Test1")
// Change an element of the first array.
firstArray.[1].Insert(0, "Test2") |> ignore
printfn "%A" firstArray
printfn "%A" secondArray


[|Test1; Test2; |]
[|; Test2; |]


Array.sub從陣列的子範圍產生新的陣列。Array.sub generates a new array from a subrange of an array. 您可以藉由提供起始索引和長度來指定子範圍。You specify the subrange by providing the starting index and the length. 下列程式碼示範 Array.sub 的用法。The following code demonstrates the use of Array.sub.

let a1 = [| 0 .. 99 |]
let a2 = Array.sub a1 5 10
printfn "%A" a2


[|5; 6; 7; 8; 9; 10; 11; 12; 13; 14|]


Array.append結合兩個現有的陣列，以建立新的陣列。Array.append creates a new array by combining two existing arrays.

printfn "%A" (Array.append [| 1; 2; 3|] [| 4; 5; 6|])


[|1; 2; 3; 4; 5; 6|]


Array.choose選取要包含在新陣列中之陣列的元素。Array.choose selects elements of an array to include in a new array. 下列程式碼示範Array.chooseThe following code demonstrates Array.choose. 請注意，陣列的元素類型不一定要符合選項類型中所傳回值的類型。Note that the element type of the array does not have to match the type of the value returned in the option type. 在此範例中，專案類型為int ，而選項是多項式elem*elem - 1函式的結果（做為浮點數）。In this example, the element type is int and the option is the result of a polynomial function, elem*elem - 1, as a floating point number.

printfn "%A" (Array.choose (fun elem -> if elem % 2 = 0 then
Some(float (elem*elem - 1))
else
None) [| 1 .. 10 |])


[|3.0; 15.0; 35.0; 63.0; 99.0|]


Array.collect在現有陣列的每個陣列元素上執行指定的函式，然後收集函數所產生的專案，並將它們結合到新的陣列中。Array.collect runs a specified function on each array element of an existing array and then collects the elements generated by the function and combines them into a new array. 下列程式碼示範Array.collectThe following code demonstrates Array.collect.

printfn "%A" (Array.collect (fun elem -> [| 0 .. elem |]) [| 1; 5; 10|])


[|0; 1; 0; 1; 2; 3; 4; 5; 0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10|]


Array.concat採用一連串的陣列，並將它們結合成單一陣列。Array.concat takes a sequence of arrays and combines them into a single array. 下列程式碼示範Array.concatThe following code demonstrates Array.concat.

Array.concat [ [|0..3|] ; [|4|] ]
//output [|0; 1; 2; 3; 4|]

Array.concat [| [|0..3|] ; [|4|] |]
//output [|0; 1; 2; 3; 4|]


[|(1, 1, 1); (1, 2, 2); (1, 3, 3); (2, 1, 2); (2, 2, 4); (2, 3, 6); (3, 1, 3);
(3, 2, 6); (3, 3, 9)|]


Array.filter採用布林條件函式，並產生新的陣列，其中只包含來自輸入陣列的條件為 true 的元素。Array.filter takes a Boolean condition function and generates a new array that contains only those elements from the input array for which the condition is true. 下列程式碼示範Array.filterThe following code demonstrates Array.filter.

printfn "%A" (Array.filter (fun elem -> elem % 2 = 0) [| 1 .. 10|])


[|2; 4; 6; 8; 10|]


Array.rev藉由反轉現有陣列的順序，產生新的陣列。Array.rev generates a new array by reversing the order of an existing array. 下列程式碼示範Array.revThe following code demonstrates Array.rev.

let stringReverse (s: string) =
System.String(Array.rev (s.ToCharArray()))

printfn "%A" (stringReverse("!dlrow olleH"))


"Hello world!"


[| 1 .. 10 |]
|> Array.filter (fun elem -> elem % 2 = 0)
|> Array.choose (fun elem -> if (elem <> 8) then Some(elem*elem) else None)
|> Array.rev
|> printfn "%A"


[|100; 36; 16; 4|]


### 多維陣列Multidimensional Arrays

let my2DArray = array2D [ [ 1; 0]; [0; 1] ]


let arrayOfArrays = [| [| 1.0; 0.0 |]; [|0.0; 1.0 |] |]
let twoDimensionalArray = Array2D.init 2 2 (fun i j -> arrayOfArrays.[i].[j])


twoDimensionalArray.[0, 1] <- 1.0


### 陣列切割和多維陣列Array Slicing and Multidimensional Arrays

// Get rows 1 to N from an NxM matrix (returns a matrix):
matrix.[1.., *]

// Get rows 1 to 3 from a matrix (returns a matrix):
matrix.[1..3, *]

// Get columns 1 to 3 from a matrix (returns a matrix):
matrix.[*, 1..3]

// Get a 3x3 submatrix:
matrix.[1..3, 1..3]


// Get row 3 from a matrix as a vector:
matrix.[3, *]

// Get column 3 from a matrix as a vector:
matrix.[*, 3]


type Matrix<'T>(N: int, M: int) =
let internalArray = Array2D.zeroCreate<'T> N M

member this.Item
with get(a: int, b: int) = internalArray.[a, b]
and set(a: int, b: int) (value:'T) = internalArray.[a, b] <- value

member this.GetSlice(rowStart: int option, rowFinish : int option, colStart: int option, colFinish : int option) =
let rowStart =
| Some(v) -> v
| None -> 0
let rowFinish =
match rowFinish with
| Some(v) -> v
| None -> internalArray.GetLength(0) - 1
let colStart =
| Some(v) -> v
| None -> 0
let colFinish =
match colFinish with
| Some(v) -> v
| None -> internalArray.GetLength(1) - 1
internalArray.[rowStart..rowFinish, colStart..colFinish]

member this.GetSlice(row: int, colStart: int option, colFinish: int option) =
let colStart =
| Some(v) -> v
| None -> 0
let colFinish =
match colFinish with
| Some(v) -> v
| None -> internalArray.GetLength(1) - 1
internalArray.[row, colStart..colFinish]

member this.GetSlice(rowStart: int option, rowFinish: int option, col: int) =
let rowStart =
| Some(v) -> v
| None -> 0
let rowFinish =
match rowFinish with
| Some(v) -> v
| None -> internalArray.GetLength(0) - 1
internalArray.[rowStart..rowFinish, col]

module test =
let generateTestMatrix x y =
let matrix = new Matrix<float>(3, 3)
for i in 0..2 do
for j in 0..2 do
matrix.[i, j] <- float(i) * x - float(j) * y
matrix

let test1 = generateTestMatrix 2.3 1.1
let submatrix = test1.[0..1, 0..1]
printfn "%A" submatrix

let firstRow = test1.[0,*]
let secondRow = test1.[1,*]
let firstCol = test1.[*,0]
printfn "%A" firstCol


### 陣列上的布耳函數Boolean Functions on Arrays

The functions Array.exists and Array.exists2 test elements in either one or two arrays, respectively. 這些函式會採用測試函式true ，並在有符合條件的元素（或Array.exists2專案組）時傳回。These functions take a test function and return true if there is an element (or element pair for Array.exists2) that satisfies the condition.

let allNegative = Array.exists (fun elem -> abs (elem) = elem) >> not
printfn "%A" (allNegative [| -1; -2; -3 |])
printfn "%A" (allNegative [| -10; -1; 5 |])
printfn "%A" (allNegative [| 0 |])

let haveEqualElement = Array.exists2 (fun elem1 elem2 -> elem1 = elem2)
printfn "%A" (haveEqualElement [| 1; 2; 3 |] [| 3; 2; 1|])


true
false
false
true


let allPositive = Array.forall (fun elem -> elem > 0)
printfn "%A" (allPositive [| 0; 1; 2; 3 |])
printfn "%A" (allPositive [| 1; 2; 3 |])

let allEqual = Array.forall2 (fun elem1 elem2 -> elem1 = elem2)
printfn "%A" (allEqual [| 1; 2 |] [| 1; 2 |])
printfn "%A" (allEqual [| 1; 2 |] [| 2; 1 |])


false
true
true
false


### 搜尋陣列Searching Arrays

Array.find採用布耳函數，並傳回函式傳回的第一個true專案， System.Collections.Generic.KeyNotFoundException如果找不到符合條件的專案，則會引發。Array.find takes a Boolean function and returns the first element for which the function returns true, or raises a System.Collections.Generic.KeyNotFoundException if no element that satisfies the condition is found. Array.findIndex類似Array.find，但它會傳回專案的索引，而不是元素本身。Array.findIndex is like Array.find, except that it returns the index of the element instead of the element itself.

let arrayA = [| 2 .. 100 |]
let delta = 1.0e-10
let isPerfectSquare (x:int) =
let y = sqrt (float x)
abs(y - round y) < delta
let isPerfectCube (x:int) =
let y = System.Math.Pow(float x, 1.0/3.0)
abs(y - round y) < delta
let element = Array.find (fun elem -> isPerfectSquare elem && isPerfectCube elem) arrayA
let index = Array.findIndex (fun elem -> isPerfectSquare elem && isPerfectCube elem) arrayA
printfn "The first element that is both a square and a cube is %d and its index is %d." element index


The first element that is both a square and a cube is 64 and its index is 62.


Array.tryFind類似于Array.find，但它的結果是選項類型， None如果找不到任何元素，則會傳回。Array.tryFind is like Array.find, except that its result is an option type, and it returns None if no element is found. Array.tryFindArray.find當您不知道相符的元素是否在陣列中時，應該使用而不是。Array.tryFind should be used instead of Array.find when you do not know whether a matching element is in the array. 同樣地Array.tryFindIndex ，類似Array.findIndex于選項類型為傳回值的例外。Similarly, Array.tryFindIndex is like Array.findIndex except that the option type is the return value. 如果找不到任何元素，則選項None為。If no element is found, the option is None.

let delta = 1.0e-10
let isPerfectSquare (x:int) =
let y = sqrt (float x)
abs(y - round y) < delta
let isPerfectCube (x:int) =
let y = System.Math.Pow(float x, 1.0/3.0)
abs(y - round y) < delta
let lookForCubeAndSquare array1 =
let result = Array.tryFind (fun elem -> isPerfectSquare elem && isPerfectCube elem) array1
match result with
| Some x -> printfn "Found an element: %d" x
| None -> printfn "Failed to find a matching element."

lookForCubeAndSquare [| 1 .. 10 |]
lookForCubeAndSquare [| 100 .. 1000 |]
lookForCubeAndSquare [| 2 .. 50 |]


Found an element: 1
Found an element: 729


Array.tryPick您需要轉換專案，以及找出元素時，請使用。Use Array.tryPick when you need to transform an element in addition to finding it. 結果是第一個專案，函式會將轉換的元素當做選項值傳回， None如果找不到這類元素，則為。The result is the first element for which the function returns the transformed element as an option value, or None if no such element is found.

let findPerfectSquareAndCube array1 =
let delta = 1.0e-10
let isPerfectSquare (x:int) =
let y = sqrt (float x)
abs(y - round y) < delta
let isPerfectCube (x:int) =
let y = System.Math.Pow(float x, 1.0/3.0)
abs(y - round y) < delta
// intFunction : (float -> float) -> int -> int
// Allows the use of a floating point function with integers.
let intFunction function1 number = int (round (function1 (float number)))
let cubeRoot x = System.Math.Pow(x, 1.0/3.0)
// testElement: int -> (int * int * int) option
// Test an element to see whether it is a perfect square and a perfect
// cube, and, if so, return the element, square root, and cube root
// as an option value. Otherwise, return None.
let testElement elem =
if isPerfectSquare elem && isPerfectCube elem then
Some(elem, intFunction sqrt elem, intFunction cubeRoot elem)
else None
match Array.tryPick testElement array1 with
| Some (n, sqrt, cuberoot) -> printfn "Found an element %d with square root %d and cube root %d." n sqrt cuberoot
| None -> printfn "Did not find an element that is both a perfect square and a perfect cube."

findPerfectSquareAndCube [| 1 .. 10 |]
findPerfectSquareAndCube [| 2 .. 100 |]
findPerfectSquareAndCube [| 100 .. 1000 |]
findPerfectSquareAndCube [| 1000 .. 10000 |]
findPerfectSquareAndCube [| 2 .. 50 |]


Found an element 1 with square root 1 and cube root 1.
Found an element 64 with square root 8 and cube root 4.
Found an element 729 with square root 27 and cube root 9.
Found an element 4096 with square root 64 and cube root 16.


### 在陣列上執行計算Performing Computations on Arrays

Array.average函式會傳回陣列中每個元素的平均值。The Array.average function returns the average of each element in an array. 它受限於支援精確除以整數的元素類型，其中包括浮點類型，而不是整數類型。It is limited to element types that support exact division by an integer, which includes floating point types but not integral types. Array.averageBy函式會傳回每個元素上呼叫函式的結果平均值。The Array.averageBy function returns the average of the results of calling a function on each element. 針對整數類型的陣列，您可以使用Array.averageBy ，並讓函式將每個專案轉換成浮點類型以進行計算。For an array of integral type, you can use Array.averageBy and have the function convert each element to a floating point type for the computation.

Array.sum加入陣列的元素，並Array.sumBy在每個專案上呼叫函式，並將結果加在一起。Array.sum adds the elements of an array, and Array.sumBy calls a function on each element and adds the results together.

The functions Array.fold, Array.foldBack, Array.reduce, Array.reduceBack, Array.scan, and Array.scanBack execute algorithms that involve all the elements of an array. 同樣地，變數Array.fold2Array.foldBack2會在兩個數組上執行計算。Similarly, the variations Array.fold2 and Array.foldBack2 perform computations on two arrays.

### 修改陣列Modifying Arrays

Array.set將元素設定為指定的值。Array.set sets an element to a specified value. Array.fill將陣列中的元素範圍設定為指定的值。Array.fill sets a range of elements in an array to a specified value. 下列程式碼提供的範例Array.fillThe following code provides an example of Array.fill.

let arrayFill1 = [| 1 .. 25 |]
Array.fill arrayFill1 2 20 0
printfn "%A" arrayFill1


[|1; 2; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 23; 24; 25|]


### 來回轉換其他類型Converting to and from Other Types

Array.ofList從清單建立陣列。Array.ofList creates an array from a list. Array.ofSeq從序列建立陣列。Array.ofSeq creates an array from a sequence. Array.toListArray.toSeq會從陣列類型轉換成這些其他集合類型。Array.toList and Array.toSeq convert to these other collection types from the array type.

### 陣列和元組Arrays and Tuples

The functions Array.zip and Array.unzip convert arrays of tuple pairs to tuples of arrays and vice versa. Array.zip3Array.unzip3很相似，不同之處在于它們會與三個數組的三個元素或元組的元組搭配使用。Array.zip3 and Array.unzip3 are similar except that they work with tuples of three elements or tuples of three arrays.