Arrays
数组是固定大小,从零开始,可变的连续数据元素集合,它们都是相同类型的。
创建数组 (Creating Arrays)
您可以使用各种语法和方法或使用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支持对一维数组的操作。
下表显示了数组的基本操作 -
值 | 描述 |
---|---|
追加:'T []→'T []→'T [] | 创建一个数组,其中包含一个数组的元素,后跟另一个数组的元素。 |
平均值:^ T []→^ T. | 返回数组中元素的平均值。 |
averageBy:('T→^ U)→'T []→^ U. | 返回通过将函数应用于数组的每个元素而生成的元素的平均值。 |
blit:'T []→int→'T []→int→int→unit | 从一个数组中读取一系列元素并将它们写入另一个数组。 |
选择:('T→U选项)→'T []→'U [] | 将提供的函数应用于数组的每个元素。 返回一个数组,其中包含函数返回Some(x)的每个元素的结果x。 |
收集:('T→'U [])→T []→'U [] | 将提供的函数应用于数组的每个元素,连接结果,并返回组合数组。 |
concat:seq →'T [] | 创建一个数组,其中包含每个提供的数组序列的元素。 |
复制:'T→'T [] | 创建一个包含所提供数组元素的数组。 |
create:int→'T→'T [] | 创建一个数组,其元素最初都是提供的值。 |
空:'T [] | 返回给定类型的空数组。 |
存在:('T→bool)→'T []→布尔 | 测试数组的任何元素是否满足提供的谓词。 |
exists2:('T1→'T2→bool)→'T1 []→'T2 []→布尔 | 测试两个数组中的任何一对相应元素是否满足所提供的条件。 |
填充:'T []→int→int→'T→单位 | 使用提供的值填充数组的一系列元素。 |
过滤器:('T→bool)→'T []→'T [] | 返回一个集合,该集合仅包含所提供条件返回true的所提供数组的元素。 |
找:('T→bool)→'T []→'T | 返回提供的函数返回true的第一个元素。 如果不存在此类元素,则引发KeyNotFoundException。 |
findIndex:('T→bool)→'T []→int | 返回满足所提供条件的数组中第一个元素的索引。 如果没有元素满足条件,则引发KeyNotFoundException。 |
fold:('State→'T→'State)→'State→'T []→'State | 将函数应用于数组的每个元素,通过计算线程化累加器参数。 如果输入函数是f并且数组元素是i0 ... iN,则此函数计算f(...(fs i0)...)iN。 |
fold2 :('状态→'T1→'T2→'状态)→'状态→'T1 []→'T2 []→'状态 | 将函数应用于来自两个提供的数组的元素对,从左到右,通过计算线程化累加器参数。 两个输入数组必须具有相同的长度; 否则,引发ArgumentException。 |
foldBack :('T→'州→'州)→'T []→'州→'州 | 将函数应用于数组的每个元素,通过计算线程化累加器参数。 如果输入函数是f并且数组元素是i0 ... iN,则此函数计算f i0(...(f iN s))。 |
foldBack2 :('T1→'T2→'状态→'状态)→'T1 []→'T2 []→'状态→'状态 | 将函数应用于来自两个提供的数组的元素对,从右到左,通过计算线程化累加器参数。 两个输入数组必须具有相同的长度; 否则,引发ArgumentException。 |
forall:('T→bool)→'T []→布尔 | 测试数组的所有元素是否满足提供的条件。 |
forall2:('T1→'T2→bool)→'T1 []→'T2 []→布尔 | 测试两个提供的数组的所有相应元素是否满足提供的条件。 |
get:'T []→int→'T | 从数组中获取元素。 |
init:int→(int→'T)→'T [] | 使用提供的函数创建提供的维度的数组。 |
isEmpty:'T []→布尔 | 测试数组是否包含任何元素。 |
iter :('T→单位)→'T []→单位 | 将提供的函数应用于数组的每个元素。 |
iter2:('T1→'T2→单位)→'T1 []→'T2 []→单位) | 将提供的函数应用于两个数组中匹配索引的一对元素。 两个数组必须具有相同的长度; 否则,引发ArgumentException。 |
iteri:(int→'T→unit)→'T []→单位 | 将提供的函数应用于数组的每个元素。 传递给函数的整数表示元素的索引。 |
iteri2:(int→'T1→'T2→单位)→'T1 []→'T2 []→单位 | 将提供的函数应用于两个数组中匹配索引的一对元素,同时传递元素的索引。 两个数组必须具有相同的长度; 否则,引发ArgumentException。 |
长度:'T []→int | 返回数组的长度。 Length属性做同样的事情。 |
地图:('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→bool)→'T []→'T [] *'T [] | 将数组拆分为两个数组,一个包含提供的条件返回true,的元素,另一个包含返回false的数组。 |
permute:(int→int)→'T []→'T [] | 根据指定的排列置换数组的元素。 |
选择:('T→'U选项)→'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 []) | 表现得像折叠,但返回中间结果和最终结果。 |
scanBack:('T→'State→'State)→'T []→'State→'State [] | 表现得像foldBack,但返回中间结果和最终结果。 |
设置:'T []→int→'T→单位 | 设置数组的元素。 |
排序:'T []→'T [] | 对数组的元素进行排序并返回一个新数组。 Operators.compare用于比较元素。 |
sortBy:('T→'Key)→'T []→'T [] | 使用提供的函数对元素的元素进行排序,以将元素转换为排序操作所基于的类型,并返回一个新数组。 Operators.compare用于比较元素。 |
sortInPlace:'T []→单位 | 使用提供的比较函数,通过更改数组来对数组元素进行排序。 Operators.compare用于比较元素。 |
sortInPlaceBy :('T→'Key)→'T []→单位 | 使用提供的键投影,通过更改数组来对数组元素进行排序。 Operators.compare用于比较元素。 |
sortInPlaceWith:('T→'T→int)→'T []→单位 | 使用提供的比较函数对数组元素进行排序,以更改数组。 |
sortWith:('T→'T→int)→'T []→'T [] | 使用提供的比较函数对数组的元素进行排序,并返回一个新数组。 |
sub:'T []→int→int→'T [] | 创建一个包含所提供的子范围的数组,该子范围由索引和长度开始指定。 |
sum:'T []→^ T. | 返回数组中元素的总和。 |
sumBy:('T→^ U)→'T []→^ U. | 返回通过将函数应用于数组的每个元素而生成的结果的总和。 |
toList:'T []→'T列表 | 将提供的数组转换为列表。 |
toSeq:'T []→seq | 将提供的数组视为序列。 |
tryFind:('T→bool)→'T []→'T选项 | 返回提供的函数返回true的提供数组中的第一个元素。 如果不存在此类元素,则返回None 。 |
tryFindIndex :('T→bool)→'T []→int选项 | 返回满足所提供条件的数组中第一个元素的索引。 |
tryPick :('T→'U选项)→'T []→'U选项 | 将提供的函数应用于提供的数组的连续元素,并返回第一个结果,其中函数返回某些x的Some(x)。 如果函数永远不会返回Some(x),则返回None 。 |
unzip:('T1 *'T2)[]→'T1 [] *'T2 [] | 将元组对的数组拆分为两个数组的元组。 |
unzip3:('T1 *'T2 *'T3)[]→'T1 [] *'T2 [] *'T3 [] | 将三个元素的元组数组拆分为三个数组的元组。 |
zeroCreate:int→'T [] | 创建一个数组,其元素最初设置为默认值Unchecked.defaultof 。 |
zip:'T1 []→'T2 []→('T1 *'T2)[] | 将两个数组合并为一个包含两个元素的元组数组。 两个数组必须具有相同的长度; 否则,引发ArgumentException。 |
zip3:'T1 []→'T2 []→'T3 []→('T1 *'T2 * 113'T3)[] | 将三个数组合并为一个具有三个元素的元组数组。 三个阵列必须具有相同的长度; 否则,引发ArgumentException。 |
在下一节中,我们将看到其中一些功能的用途。
使用函数创建数组 (Creating Arrays Using Functions)
Array模块提供了几个从头开始创建数组的函数。
Array.empty函数创建一个新的空数组。
Array.create函数创建一个指定大小的数组,并将所有元素设置为给定值。
Array.init函数创建一个数组,给定一个维度和一个生成元素的函数。
Array.zeroCreate函数创建一个数组,其中所有元素都初始化为零值。
Array.copy函数创建一个新数组,其中包含从现有数组复制的元素。
Array.sub函数从数组的子范围生成一个新数组。
Array.append函数通过组合两个现有数组来创建一个新数组。
Array.choose函数选择要包含在新数组中的数组元素。
Array.collect函数在现有数组的每个数组元素上运行指定的函数,然后收集函数生成的元素并将它们组合成一个新数组。
Array.concat函数接受一系列数组并将它们组合成一个数组。
Array.filter函数采用布尔条件函数并生成一个新数组,该数组仅包含条件为true的输入数组中的那些元素。
Array.rev函数通过反转现有数组的顺序生成新数组。
以下示例演示了这些功能 -
例子1 (Example 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 (Example 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函数接受一个Boolean函数并返回函数返回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.