- F# 基础教程
- F# - 主页
- F# - 概述
- F# - 环境设置
- F# - 程序结构
- F# - 基本语法
- F# - 数据类型
- F# - 变量
- F# - 运算符
- F# - 决策
- F# - 循环
- F# - 函数
- F# - 字符串
- F# - 选项
- F# - 元组
- F# - 记录
- F# - 列表
- F# - 序列
- F# - 集
- F# - 地图
- F# - 受歧视的工会
- F# - 可变数据
- F# - 数组
- F# - 可变列表
- F# - 可变字典
- F# - 基本 I/O
- F# - 泛型
- F# - 代表
- F# - 枚举
- F# - 模式匹配
- F# - 异常处理
- F# - 类
- F# - 结构
- F# - 运算符重载
- F# - 继承
- F# - 接口
- F# - 事件
- F# - 模块
- F# - 命名空间
- F# 有用资源
- F# - 快速指南
- F# - 有用的资源
- F# - 讨论
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 支持对一维数组的操作。
下表显示了数组的基本操作 -
价值 | 描述 |
---|---|
追加:'T[] → 'T[] → 'T[] | 创建一个数组,其中包含一个数组的元素,后跟另一个数组的元素。 |
平均值 : ^T [] → ^T | 返回数组中元素的平均值。 |
平均:('T → ^U) → 'T [] → ^U | 返回通过将函数应用于数组的每个元素而生成的元素的平均值。 |
blit : 'T[] → int → 'T[] → int → int → 单位 | 从一个数组中读取一系列元素并将它们写入另一个数组中。 |
选择:('T→U选项)→'T[]→'U[] | 将提供的函数应用于数组的每个元素。返回一个数组,其中包含函数返回 Some(x) 的每个元素的结果 x。 |
收集:('T→'U[])→T[]→'U[] | 将提供的函数应用于数组的每个元素,连接结果并返回组合数组。 |
concat : seq<'T []> → 'T [] | 创建一个数组,其中包含每个提供的数组序列的元素。 |
复制:'T → 'T [] | 创建一个包含所提供数组的元素的数组。 |
创建:int → 'T → 'T [] | 创建一个数组,其元素最初都是提供的值。 |
空:'T [] | 返回给定类型的空数组。 |
存在:('T → bool) → 'T [] → bool | 测试数组的任何元素是否满足提供的谓词。 |
存在2:('T1→'T2→布尔)→'T1[]→'T2[]→布尔 | 测试两个数组的任意一对对应元素是否满足提供的条件。 |
填充:'T[]→int→int→'T→单位 | 使用提供的值填充数组的一系列元素。 |
过滤器:('T→bool)→'T[]→'T[] | 返回一个集合,该集合仅包含所提供的数组中所提供的条件返回true的元素。 |
查找:('T → bool) → 'T [] → 'T | 返回所提供的函数返回true的第一个元素。如果不存在此类元素,则引发 KeyNotFoundException。 |
findIndex : ('T → bool) → 'T [] → int | 返回数组中满足所提供条件的第一个元素的索引。如果没有元素满足条件,则引发 KeyNotFoundException。 |
折叠 : ('状态→'T→'状态)→'状态→'T[]→'状态 | 将函数应用于数组的每个元素,通过计算线程化累加器参数。如果输入函数为 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 → 布尔) → 'T [] → 布尔 | 测试数组的所有元素是否满足提供的条件。 |
forall2 : ('T1 → 'T2 → bool) → 'T1 [] → 'T2 [] → bool | 测试两个提供的数组的所有对应元素是否满足提供的条件。 |
得到:'T[]→int→'T | 从数组中获取一个元素。 |
初始化:int → (int → 'T) → 'T [] | 使用提供的函数创建提供维度的数组。 |
isEmpty : 'T [] → 布尔 | 测试数组是否有元素。 |
iter : ('T → 单位) → 'T [] → 单位 | 将提供的函数应用于数组的每个元素。 |
iter2 : ('T1→'T2→单位)→'T1[]→'T2[]→单位) | 将提供的函数应用于两个数组中匹配索引的一对元素。两个数组的长度必须相同;否则,将引发 ArgumentException。 |
iteri : (int → 'T → 单位) → '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。 |
最大值 : 'T [] → 'T | 返回数组所有元素中最大的一个。Operators.max 用于比较元素。 |
maxBy : ('T → 'U) → 'T [] → 'T | 返回数组所有元素中最大的元素,通过 Operators.max 对函数结果进行比较。 |
分钟 : ('T [] → 'T | 返回数组所有元素中的最小元素。Operators.min 用于比较元素。 |
minBy : ('T → 'U) → 'T [] → 'T | 返回数组所有元素中的最小元素。Operators.min 用于比较元素。 |
ofList : 'T 列表 → 'T [] | 从提供的列表创建一个数组。 |
ofSeq : seq<'T> → 'T [] | 从提供的可枚举对象创建一个数组。 |
分区 : ('T → bool) → 'T[] → 'T[] * 'T[] | 将数组拆分为两个数组,一个数组包含所提供的条件返回true 的元素,另一个数组包含返回false 的元素。 |
排列:(int → int) → 'T [] → 'T [] | 根据指定的排列对数组的元素进行排列。 |
pick : ('T → 'U 选项) → 'T [] → 'U | 将提供的函数应用于所提供数组的连续元素,返回第一个结果,其中函数针对某些 x 返回 Some(x)。如果函数从不返回 Some(x),则会引发 KeyNotFoundException。 |
减少 : ('T → 'T → 'T) → 'T [] → 'T | 将函数应用于数组的每个元素,通过计算线程化累加器参数。如果输入函数为 f 并且数组元素为 i0...iN,则该函数计算 f (...(f i0 i1)...) iN。如果数组的大小为零,则引发 ArgumentException。 |
减少返回:('T→'T→'T)→'T[]→'T | 将函数应用于数组的每个元素,通过计算线程化累加器参数。如果输入函数为 f 并且元素为 i0...iN,则该函数计算 f i0 (...(f iN-1 iN))。如果数组的大小为零,则引发 ArgumentException。 |
转 : 'T [] → 'T [] | 反转所提供数组中元素的顺序。 |
扫描:('状态→'T→'状态)→'状态→'T[]→'状态[]) | Behave类似于折叠,但将中间结果与最终结果一起返回。 |
scanBack : ('T→'状态→'状态)→'T[]→'状态→'状态[] | Behave类似于foldBack,但将中间结果与最终结果一起返回。 |
设置:'T[]→整数→'T→单位 | 设置数组的一个元素。 |
排序:'T[]→'T[] | 对数组的元素进行排序并返回一个新数组。Operators.compare 用于比较元素。 |
排序依据:('T→'键)→'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[] | 创建一个包含所提供的子范围的数组,该子范围由起始索引和长度指定。 |
总和:'T [] → ^T | 返回数组中元素的总和。 |
sumBy : ('T → ^U) → 'T [] → ^U | 返回通过将函数应用于数组的每个元素而生成的结果的总和。 |
toList : 'T[] → 'T 列表 | 将提供的数组转换为列表。 |
toSeq : 'T[] → seq<'T> | 将提供的数组视为序列。 |
tryFind : ('T → bool) → 'T [] → 'T 选项 | 返回所提供数组中所提供函数返回true 的第一个元素。如果不存在这样的元素,则返回None 。 |
tryFindIndex : ('T → bool) → 'T [] → int 选项 | 返回数组中满足所提供条件的第一个元素的索引。 |
tryPick : ('T → 'U 选项) → 'T [] → 'U 选项 | 将提供的函数应用于所提供数组的连续元素,并返回第一个结果,其中函数针对某些 x 返回 Some(x)。如果函数从不返回 Some(x),则返回None 。 |
解压:('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函数采用布尔条件函数并生成一个新数组,该数组仅包含输入数组中条件为 true 的元素。
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函数的工作原理类似,只是它返回元素的索引而不是元素本身。
以下示例演示了这一点。
微软提供了这个有趣的程序示例,它找到给定数字范围内的第一个元素,它既是完美的平方也是完美的立方 -
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.