F# - 陣列



陣列是固定大小、從零開始、可變的連續資料元素集合,這些元素都屬於相同的型別。

建立陣列

您可以使用各種語法和方法或使用 Array 模組中的函式來建立陣列。在本節中,我們將討論在不使用模組函式的情況下建立陣列。

在不使用函式的情況下,有三種建立陣列的語法方法:

  • 列出 [| 和 |] 之間的連續值,並用分號分隔。
  • 將每個元素放在單獨一行,在這種情況下,分號分隔符是可選的。
  • 使用序列表達式。

您可以使用點運算子 (.) 和方括號 ([ 和 ]) 訪問陣列元素。

以下示例演示瞭如何建立陣列:

//using semicolon separator
let array1 = [| 1; 2; 3; 4; 5; 6 |]
for i in 0 .. array1.Length - 1 do
   printf "%d " array1.[i]
printfn" "

// without semicolon separator
let array2 =
   [|
      1
      2
      3
      4
      5
   |]
for i in 0 .. array2.Length - 1 do
   printf "%d " array2.[i]
printfn" "

//using sequence
let array3 = [| for i in 1 .. 10 -> i * i |]
for i in 0 .. array3.Length - 1 do
   printf "%d " array3.[i]
printfn" "

編譯並執行程式時,將生成以下輸出:

1 2 3 4 5 6
1 2 3 4 5
1 4 9 16 25 36 49 64 81 100

陣列的基本操作

庫模組 Microsoft.FSharp.Collections.Array 支援對一維陣列的操作。

下表顯示了陣列的基本操作:

描述
append : 'T [] → 'T [] → 'T [] 建立一個包含一個數組的元素後跟另一個數組的元素的陣列。
average : ^T [] → ^T 返回陣列中元素的平均值。
averageBy : ('T → ^U) → 'T [] → ^U 返回將函式應用於陣列的每個元素生成的元素的平均值。
blit : 'T [] → int → 'T [] → int → int → unit 讀取一個數組中的一系列元素並將它們寫入另一個數組。
choose : ('T → U option) → 'T [] → 'U [] 將提供的函式應用於陣列的每個元素。返回一個數組,其中包含每個元素的結果 x,對於這些元素,函式返回 Some(x)。
collect : ('T → 'U []) → T [] → 'U [] 將提供的函式應用於陣列的每個元素,連線結果,並返回組合的陣列。
concat : seq<'T []> → 'T [] 建立一個包含提供的陣列序列的每個元素的元素的陣列。
copy : 'T → 'T [] 建立一個包含提供的陣列的元素的陣列。
create : int → 'T → 'T [] 建立一個數組,其元素最初都是提供的值。
empty : 'T [] 返回給定型別的空陣列。
exists : ('T → bool) → 'T [] → bool 測試陣列的任何元素是否滿足提供的謂詞。
exists2 : ('T1 → 'T2 → bool) → 'T1 [] → 'T2 [] → bool 測試兩個陣列的任何一對對應元素是否滿足提供的條件。
fill : 'T [] → int → int → 'T → unit 用提供的值為陣列的一系列元素填充。
filter : ('T → bool) → 'T [] → 'T [] 返回一個集合,其中僅包含提供的陣列中提供的條件返回 true 的元素。
find : ('T → bool) → 'T [] → 'T 返回提供的函式返回 true 的第一個元素。如果不存在這樣的元素,則引發 KeyNotFoundException。
findIndex : ('T → bool) → 'T [] → int 返回陣列中第一個滿足提供的條件的元素的索引。如果元素都不滿足該條件,則引發 KeyNotFoundException。
fold : ('State → 'T → 'State) → 'State → 'T [] → 'State 將函式應用於陣列的每個元素,將累加器引數貫穿計算。如果輸入函式是 f 並且陣列元素是 i0...iN,則此函式計算 f (...(f s i0)...) iN。
fold2 : ('State → 'T1 → 'T2 → 'State) → 'State → 'T1 [] → 'T2 [] → 'State 將函式應用於兩個提供的陣列中元素對,從左到右,將累加器引數貫穿計算。兩個輸入陣列必須具有相同的長度;否則,將引發 ArgumentException。
foldBack : ('T → 'State → 'State) → 'T [] → 'State → 'State 將函式應用於陣列的每個元素,將累加器引數貫穿計算。如果輸入函式是 f 並且陣列元素是 i0...iN,則此函式計算 f i0 (...(f iN s))。
foldBack2 : ('T1 → 'T2 → 'State → 'State) → 'T1 [] → 'T2 [] → 'State → 'State 將函式應用於兩個提供的陣列中元素對,從右到左,將累加器引數貫穿計算。兩個輸入陣列必須具有相同的長度;否則,將引發 ArgumentException。
forall : ('T → bool) → 'T [] → bool 測試陣列的所有元素是否滿足提供的條件。
forall2 : ('T1 → 'T2 → bool) → 'T1 [] → 'T2 [] → bool 測試兩個提供的陣列的所有對應元素是否滿足提供的條件。
get : 'T [] → int → 'T 從陣列中獲取元素。
init : int → (int → 'T) → 'T [] 使用提供的函式建立指定維度的陣列。
isEmpty : 'T [] → bool 測試陣列是否有任何元素。
iter : ('T → unit) → 'T [] → unit 將提供的函式應用於陣列的每個元素。
iter2 : ('T1 → 'T2 → unit) → 'T1 [] → 'T2 [] → unit) 將提供的函式應用於兩個陣列中匹配索引的一對元素。兩個陣列必須具有相同的長度;否則,將引發 ArgumentException。
iteri : (int → 'T → unit) → 'T [] → unit 將提供的函式應用於陣列的每個元素。傳遞給函式的整數指示元素的索引。
iteri2 : (int → 'T1 → 'T2 → unit) → 'T1 [] → 'T2 [] → unit 將提供的函式應用於兩個陣列中匹配索引的一對元素,還傳遞元素的索引。兩個陣列必須具有相同的長度;否則,將引發 ArgumentException。
length : 'T [] → int 返回陣列的長度。Length 屬性執行相同操作。
map : ('T → 'U) → 'T [] → 'U [] 建立一個數組,其元素是將提供的函式應用於提供的陣列的每個元素的結果。
map2 : ('T1 → 'T2 → 'U) → 'T1 [] → 'T2 [] → 'U [] 建立一個數組,其元素是將提供的函式應用於兩個提供的陣列的對應元素的結果。兩個輸入陣列必須具有相同的長度;否則,將引發 ArgumentException。
mapi : (int → 'T → 'U) → 'T [] → 'U [] 建立一個數組,其元素是將提供的函式應用於提供的陣列的每個元素的結果。傳遞給函式的整數索引指示正在轉換的元素的索引。
mapi2 : (int → 'T1 → 'T2 → 'U) → 'T1 [] → 'T2 [] → 'U [] 建立一個數組,其元素是將提供的函式應用於兩個集合的對應元素成對的結果,還傳遞元素的索引。兩個輸入陣列必須具有相同的長度;否則,將引發 ArgumentException。
max : 'T [] → 'T 返回陣列所有元素中最大的一個。Operators.max 用於比較元素。
maxBy : ('T → 'U) → 'T [] → 'T 返回陣列所有元素中最大的一個,透過函式結果上的 Operators.max 進行比較。
min : ('T [] → 'T 返回陣列所有元素中最小的一個。Operators.min 用於比較元素。
minBy : ('T → 'U) → 'T [] → 'T 返回陣列所有元素中最小的一個。Operators.min 用於比較元素。
ofList : 'T list → 'T [] 從提供的列表建立陣列。
ofSeq : seq<'T> → 'T [] 從提供的可列舉物件建立陣列。
partition : ('T → bool) → 'T [] → 'T [] * 'T [] 將陣列拆分為兩個陣列,一個包含提供的條件返回 true 的元素,另一個包含返回 false 的元素。
permute : (int → int) → 'T [] → 'T [] 根據指定的排列對陣列的元素進行排列。
pick : ('T → 'U option) → 'T [] → 'U 將提供的函式應用於提供的陣列的連續元素,返回函式為某個 x 返回 Some(x) 的第一個結果。如果函式從未返回 Some(x),則引發 KeyNotFoundException。
reduce : ('T → 'T → 'T) → 'T [] → 'T 將函式應用於陣列的每個元素,將累加器引數貫穿計算。如果輸入函式是 f 並且陣列元素是 i0...iN,則此函式計算 f (...(f i0 i1)...) iN。如果陣列大小為零,則引發 ArgumentException。
reduceBack : ('T → 'T → 'T) → 'T [] → 'T

將函式應用於陣列的每個元素,並將累加器引數貫穿計算過程。如果輸入函式為 f,元素為 i0...iN,則此函式計算 f i0 (...(f iN-1 iN))。如果陣列大小為零,則引發 ArgumentException。
rev : 'T [] → 'T [] 反轉提供的陣列中元素的順序。
scan : ('State → 'T → 'State) → 'State → 'T [] → 'State []) 行為類似於 fold,但會將中間結果與最終結果一起返回。
scanBack : ('T → 'State → 'State) → 'T [] → 'State → 'State [] 行為類似於 foldBack,但會將中間結果與最終結果一起返回。
set : 'T [] → int → 'T → unit 設定陣列中的一個元素。
sort : 'T[] → 'T [] 對陣列中的元素進行排序並返回一個新陣列。使用 Operators.compare 來比較元素。
sortBy : ('T → 'Key) → 'T [] → 'T [] 使用提供的函式將元素轉換為排序操作所基於的型別,對陣列中的元素進行排序,並返回一個新陣列。使用 Operators.compare 來比較元素。
sortInPlace : 'T [] → unit 透過就地更改陣列來對陣列中的元素進行排序,使用提供的比較函式。使用 Operators.compare 來比較元素。
sortInPlaceBy : ('T → 'Key) → 'T [] → unit 透過就地更改陣列來對陣列中的元素進行排序,使用提供的鍵投影。使用 Operators.compare 來比較元素。
sortInPlaceWith : ('T → 'T → int) → 'T [] → unit 使用提供的比較函式對陣列中的元素進行排序,並就地更改陣列。
sortWith : ('T → 'T → int) → 'T [] → 'T [] 使用提供的比較函式對陣列中的元素進行排序,並返回一個新陣列。
sub : 'T [] → int → int → 'T [] 建立一個包含提供的子範圍的陣列,該子範圍由起始索引和長度指定。
sum : 'T [] → ^T 返回陣列中元素的總和。
sumBy : ('T → ^U) → 'T [] → ^U 返回將函式應用於陣列的每個元素後生成的每個結果的總和。
toList : 'T [] → 'T list 將提供的陣列轉換為列表。
toSeq : 'T [] → seq<'T> 將提供的陣列視為一個序列。
tryFind : ('T → bool) → 'T [] → 'T option 返回提供的陣列中第一個使提供的函式返回 true 的元素。如果不存在這樣的元素,則返回 None
tryFindIndex : ('T → bool) → 'T [] → int option 返回陣列中第一個滿足提供的條件的元素的索引。
tryPick : ('T → 'U option) → 'T [] → 'U option 將提供的函式應用於提供的陣列的連續元素,並返回函式返回 Some(x)(對於某個 x)的第一個結果。如果函式從未返回 Some(x),則返回 None
unzip : ('T1 * 'T2) [] → 'T1 [] * 'T2 [] 將元組對陣列拆分為兩個陣列的元組。
unzip3 : ('T1 * 'T2 * 'T3) [] → 'T1 [] * 'T2 [] * 'T3 [] 將三個元素的元組陣列拆分為三個陣列的元組。
zeroCreate : int → 'T [] 建立一個數組,其元素最初設定為預設值 Unchecked.defaultof<'T>。
zip : 'T1 [] → 'T2 [] → ('T1 * 'T2) [] 將兩個陣列組合成一個有兩個元素的元組陣列。這兩個陣列必須具有相同的長度;否則,將引發 ArgumentException。
zip3 : 'T1 [] → 'T2 [] → 'T3 [] → ('T1 * 'T2 * 113 'T3) [] 將三個陣列組合成一個有三個元素的元組陣列。這三個陣列必須具有相同的長度;否則,將引發 ArgumentException。

在下一節中,我們將看到其中一些功能的用法。

使用函式建立陣列

Array 模組提供了一些從頭開始建立陣列的函式。

  • Array.empty 函式建立一個新的空陣列。

  • Array.create 函式建立一個指定大小的陣列,並將所有元素設定為給定值。

  • Array.init 函式建立一個數組,給定一個維度和一個生成元素的函式。

  • Array.zeroCreate 函式建立一個數組,其中所有元素都初始化為零值。

  • Array.copy 函式建立一個新陣列,其中包含從現有陣列複製的元素。

  • Array.sub 函式從陣列的子範圍生成一個新陣列。

  • Array.append 函式透過組合兩個現有陣列來建立一個新陣列。

  • Array.choose 函式選擇陣列的元素以包含在新陣列中。

  • Array.collect 函式對現有陣列的每個陣列元素執行指定的函式,然後收集函式生成的元素並將它們組合到一個新陣列中。

  • Array.concat 函式獲取一系列陣列並將它們組合成一個數組。

  • Array.filter 函式獲取一個布林條件函式,並生成一個新陣列,其中只包含輸入陣列中條件為真的那些元素。

  • Array.rev 函式透過反轉現有陣列的順序來生成一個新陣列。

以下示例演示了這些函式 -

示例 1

(* using create and set *)
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)
printfn " "

(* empty array *)
let array2 = Array.empty
printfn "Length of empty array: %d" array2.Length

let array3 = Array.create 10 7.0
printfn "Float Array: %A" array3

(* using the init and zeroCreate *)
let array4 = Array.init 10 (fun index -> index * index)
printfn "Array of squares: %A" array4

let array5 : float array = Array.zeroCreate 10
let (myZeroArray : float array) = Array.zeroCreate 10
printfn "Float Array: %A" array5

編譯並執行程式時,將生成以下輸出:

0 1 2 3 4 5 6 7 8 9
Length of empty array: 0
Float Array: [|7.0; 7.0; 7.0; 7.0; 7.0; 7.0; 7.0; 7.0; 7.0; 7.0|]
Array of squares: [|0; 1; 4; 9; 16; 25; 36; 49; 64; 81|]
Float Array: [|0.0; 0.0; 0.0; 0.0; 0.0; 0.0; 0.0; 0.0; 0.0; 0.0|]

示例 2

(* creating subarray from element 5 *)
(* containing 15 elements thereon *)

let array1 = [| 0 .. 50 |]
let array2 = Array.sub array1 5 15
printfn "Sub Array:"
printfn "%A" array2

(* appending two arrays *)
let array3 = [| 1; 2; 3; 4|]
let array4 = [| 5 .. 9 |]
printfn "Appended Array:"
let array5 = Array.append array3 array4
printfn "%A" array5

(* using the Choose function *)
let array6 = [| 1 .. 20 |]
let array7 = Array.choose (fun elem -> if elem % 3 = 0 then
   Some(float (elem))
      else
   None) array6

printfn "Array with Chosen elements:"
printfn "%A" array7

(*using the Collect function *)
let array8 = [| 2 .. 5 |]
let array9 = Array.collect (fun elem -> [| 0 .. elem - 1 |]) array8
printfn "Array with collected elements:"
printfn "%A" array9

編譯並執行程式時,將生成以下輸出:

Sub Array:
[|5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16; 17; 18; 19|]
Appended Array:
[|1; 2; 3; 4; 5; 6; 7; 8; 9|]
Array with Chosen elements:
[|3.0; 6.0; 9.0; 12.0; 15.0; 18.0|]
Array with collected elements:
[|0; 1; 0; 1; 2; 0; 1; 2; 3; 0; 1; 2; 3; 4|]

搜尋陣列

Array.find 函式獲取一個布林函式,並返回第一個使函式返回 true 的元素,否則引發 KeyNotFoundException。

Array.findIndex 函式的工作方式類似,只是它返回元素的索引而不是元素本身。

以下示例演示了這一點。

Microsoft 提供了這個有趣的程式示例,它查詢給定數字範圍內第一個既是完全平方數又是完全立方數的元素 -

let array1 = [| 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) array1

let index = Array.findIndex (fun elem -> isPerfectSquare elem && isPerfectCube elem) array1

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.
廣告

© . All rights reserved.