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 []

将提供的函数应用于数组的每个元素.返回一个数组,其中包含函数返回Some(x)的每个元素的结果x.

collect : ('T → 'U []) → T []   → 'U []

将提供的函数应用于数组的每个元素,连接结果,并返回组合数组.

concat : seq<'T []> &rarr; 'T []

创建一个数组,其中包含每个提供的数组序列的元素.

copy : 'T &rarr; 'T []

创建一个包含所提供数组元素的数组.

create : int &rarr; 'T &rarr; 'T []

创建一个数组,其元素最初都是提供的值.

empty : 'T []

返回给定类型的空数组.

exists : ('T &rarr; bool) &rarr; 'T []   &rarr; bool

测试数组的任何元素是否满足提供的谓词.

exists2 : ('T1 &rarr; 'T2 &rarr; bool)   &rarr; 'T1 [] &rarr; 'T2 [] &rarr; bool

测试两个数组的任何一对相应元素是否满足所提供的条件.

fill : 'T [] &rarr; int &rarr; int &rarr;   'T &rarr; unit

使用提供的值填充数组的一系列元素.

filter : ('T &rarr; bool) &rarr; 'T []   &rarr; 'T []

返回一个集合,该集合仅包含所提供条件返回的提供数组的元素 true .

find : ('T &rarr; bool) &rarr; 'T [] &rarr;   'T

返回所提供函数返回的第一个元素 true .如果不存在这样的元素,则引发KeyNotFoundException.

findIndex : ('T &rarr; bool) &rarr; 'T []   &rarr; int

返回满足所提供条件的数组中第一个元素的索引.如果没有元素满足条件,则引发KeyNotFoundException.

fold : ('State &rarr; 'T &rarr; 'State)   &rarr; 'State &rarr; 'T [] &rarr; 'State

将函数应用于数组的每个元素,通过计算线程化累加器参数.如果输入函数是f并且数组元素是i0 ... iN,则此函数计算f(...(fs i0)...)iN.

fold2 : ('State &rarr; 'T1 &rarr; 'T2   &rarr; 'State) &rarr; 'State &rarr; 'T1 [] &rarr; 'T2 []   &rarr; 'State

将函数应用于两个提供的数组中的元素对,从左到右,通过计算线程化累加器参数.两个输入数组必须具有相同的长度;否则,引发ArgumentException.

foldBack : ('T &rarr; 'State &rarr; 'State)   &rarr; 'T [] &rarr; 'State &rarr; 'State

将函数应用于数组的每个元素,通过计算线程化累加器参数.如果输入函数是f并且数组元素是i0 ... iN,则此函数计算f i0(...(f iN s)).

foldBack2 : ('T1 &rarr; 'T2 &rarr; 'State   &rarr; 'State) &rarr; 'T1 [] &rarr; 'T2 [] &rarr; 'State   &rarr; 'State

将函数应用于两个提供的数组中的元素对,从右到左,通过计算线程化累加器参数.两个输入数组必须具有相同的长度;否则,引发ArgumentException.

forall : ('T &rarr; bool) &rarr; 'T []   &rarr; bool

测试数组的所有元素是否满足提供的条件.

forall2 : ('T1 &rarr; 'T2 &rarr; bool)   &rarr; 'T1 [] &rarr; 'T2 [] &rarr; bool

测试两个提供的数组的所有相应元素是否满足提供的条件.

get : 'T [] &rarr; int &rarr; 'T

从数组中获取一个元素.

init : int &rarr; (int &rarr; 'T) &rarr; 'T   []

使用提供的函数创建所提供维度的数组.

isEmpty : 'T [] &rarr; bool

测试一个数组是否有任何元素.

iter : ('T &rarr; unit) &rarr; 'T [] &rarr;   unit

将提供的函数应用于数组的每个元素.

iter2 : ('T1 &rarr; 'T2 &rarr; unit) &rarr;   'T1 [] &rarr; 'T2 [] &rarr; unit)

将提供的函数应用于两个数组中匹配索引的一对元素.两个数组必须具有相同的长度;否则,引发ArgumentException.

iteri : (int &rarr; 'T &rarr; unit) &rarr;   'T [] &rarr; unit

将提供的函数应用于数组的每个元素.传递给函数的整数表示元素的索引.

iteri2 : (int &rarr; 'T1 &rarr; 'T2 &rarr;   unit) &rarr; 'T1 [] &rarr; 'T2 [] &rarr; unit

将提供的函数应用于两个数组中匹配索引的一对元素,同时传递元素的索引.两个数组必须具有相同的长度;否则,会引发ArgumentException.

length : 'T [] &rarr; int

返回数组的长度. Length属性做同样的事情.

map : ('T &rarr; 'U) &rarr; 'T [] &rarr; 'U   []

创建一个数组,其元素是将提供的函数应用于提供的数组的每个元素的结果.

map2 : ('T1 &rarr; 'T2 &rarr; 'U) &rarr;   'T1 [] &rarr; 'T2 [] &rarr; 'U []

创建一个数组,其元素是将提供的函数应用于两个提供的数组的相应元素的结果.两个输入数组必须具有相同的长度;否则,引发ArgumentException.

mapi : (int &rarr; 'T &rarr; 'U) &rarr; 'T   [] &rarr; 'U []

创建一个数组,其元素是将提供的函数应用于所提供数组的每个元素的结果.传递给函数的整数索引表示正在转换的元素的索引.

mapi2 : (int &rarr; 'T1 &rarr; 'T2 &rarr;   'U) &rarr; 'T1 [] &rarr; 'T2 [] &rarr; 'U []

创建一个数组,其元素是将提供的函数成对应用于两个集合的相应元素的结果,同时传递元素的索引.两个输入数组必须具有相同的长度;否则,引发ArgumentException.

max : 'T [] &rarr; 'T

返回数组中所有元素中最大的元素. Operators.max用于比较元素.

maxBy : ('T &rarr; 'U) &rarr; 'T [] &rarr;   'T

返回数组中所有元素中最大的元素,通过函数结果上的Operators.max进行比较.

min : ('T [] &rarr; 'T

返回数组中所有元素中的最小元素.Operators.min用于比较元素.

minBy : ('T &rarr; 'U) &rarr; 'T [] &rarr;   'T

返回数组中所有元素中最小的元素.运算符.min用于比较元素.

ofList : 'T list &rarr; 'T []

从提供的列表中创建一个数组.

ofSeq : seq<'T> &rarr; 'T []

从提供的可枚举对象创建一个数组.

partition : ('T &rarr; bool) &rarr; 'T []   &rarr; 'T [] * 'T []

将数组拆分为两个数组,一个包含所提供条件返回的元素 true和其他包含它返回的那些 false .

permute : (int &rarr; int) &rarr; 'T []   &rarr; 'T []

根据指定的排列来置换数组的元素.

pick : ('T &rarr; 'U option) &rarr; 'T []   &rarr; 'U

将提供的函数应用于所提供数组的连续元素,返回第一个结果,其中函数返回某些xSome(x).如果函数永远不会返回Some(x),则引发KeyNotFoundException.

reduce : ('T &rarr; 'T &rarr; 'T) &rarr; 'T   [] &rarr; 'T

将函数应用于数组的每个元素,通过计算线程化累加器参数.如果输入函数是f并且数组元素是i0 ... iN,则此函数计算f(...(f i0 i1)...)iN.如果数组的大小为零,则引发ArgumentException.

reduceBack : ('T &rarr; 'T &rarr; 'T)   &rarr; 'T [] &rarr; 'T

将函数应用于数组的每个元素,通过计算线程化累加器参数.如果输入函数为f且元素为i0 ... iN,则此函数计算f i0(...(f iN-1 iN)).如果数组的大小为零,则引发ArgumentException.

rev : 'T [] &rarr; 'T []

反转所提供数组中元素的顺序.

scan : ('State &rarr; 'T &rarr; 'State)   &rarr; 'State &rarr; 'T [] &rarr; 'State [])

表现得像折叠,但返回中间结果和最终结果.

scanBack : ('T &rarr; 'State &rarr; 'State)   &rarr; 'T [] &rarr; 'State &rarr; 'State []

表现得像foldBack,但返回中间结果和最终结果.

set : 'T [] &rarr; int &rarr; 'T &rarr;   unit

设置数组的元素.

sort : 'T[] &rarr; 'T []

对数组的元素进行排序并返回一个新数组. Operators.compare用于比较元素.

sortBy : ('T &rarr; 'Key) &rarr; 'T []   &rarr; 'T []

使用提供的函数对元素的元素进行排序,以将元素转换为排序操作所基于的类型,并返回一个新数组. Operators.compare用于比较元素.

sortInPlace : 'T [] &rarr; unit

使用提供的比较函数,通过更改数组来对数组元素进行排序. Operators.compare用于比较元素.

sortInPlaceBy : ('T &rarr; 'Key) &rarr; 'T []   &rarr; unit

使用提供的键投影,通过更改数组来对数组元素进行排序. Operators.compare用于比较元素.

sortInPlaceWith : ('T &rarr; 'T &rarr; int)   &rarr; 'T [] &rarr; unit

使用提供的比较函数对数组元素进行排序,以便更改数组.

sortWith : ('T &rarr; 'T &rarr; int) &rarr;   'T [] &rarr; 'T []

使用提供的比较函数对数组元素进行排序,并返回一个新数组.

sub : 'T [] &rarr; int &rarr; int &rarr; 'T   []

创建一个包含所提供的子范围的数组,该子范围由起始索引和长度指定.

sum : 'T [] &rarr; ^T

返回数组中元素的总和.

sumBy : ('T &rarr; ^U) &rarr; 'T [] &rarr;   ^U

返回通过将函数应用于数组的每个元素而生成的结果的总和.

toList : 'T [] &rarr; 'T list

将提供的数组转换为列表.

toSeq : 'T [] &rarr; seq<'T>

将提供的数组视为序列.

tryFind : ('T &rarr; bool) &rarr; 'T []   &rarr; 'T option

返回所提供函数返回 true 的所提供数组中的第一个元素.如果不存在这样的元素,则返回.

tryFindIndex : ('T &rarr; bool) &rarr; 'T []   &rarr; int option

返回满足所提供条件的数组中第一个元素的索引.

tryPick : ('T &rarr; 'U option) &rarr; 'T []   &rarr; 'U option

将提供的函数应用于所提供数组的连续元素,并返回第一个结果,其中函数返回某些xSome(x).如果函数永远不会返回Some(x),则返回.

unzip : ('T1 * 'T2) [] &rarr; 'T1 [] * 'T2 []

将一对元组对拆分为两个数组的元组.

unzip3 : ('T1 * 'T2 * 'T3) [] &rarr; 'T1 [] * 'T2   [] * 'T3 []

将三个元素的元组数组拆分为三个数组的元组.

zeroCreate : int &rarr; 'T []

创建一个数组,其元素最初设置为默认值Unchecked.defaultof<'T>.

zip : 'T1 [] &rarr; 'T2 [] &rarr; ('T1 * 'T2)   []

将两个数组合并为一个包含两个元素的元组数组.两个数组必须具有相同的长度;否则,引发ArgumentException.

zip3 : 'T1 [] &rarr; 'T2 [] &rarr; 'T3 []   &rarr; ('T1 * 'T2 * 113 'T3) []

将三个数组合并为一个包含三个元素的元组数组.三个阵列必须具有相同的长度;否则,引发ArgumentException.

在下一节中,我们将看到其中一些功能的用途.

使用函数创建数组

Array模块提供了几个从头开始创建数组的函数.

  • Array.empty 函数创建一个新的空数组.

  • Array.create 函数创建一个指定大小的数组,并将所有元素设置为给定值.

  • Array.init 函数创建一个数组,给定一个维度和一个生成元素的函数.

  • Array.zeroCreate function创建一个数组,其中所有元素都初始化为零值.

  • 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.