- 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# - 列表
在 F# 中,列表是一系列有序的、不可变的相同类型的元素。它在某种程度上相当于链表数据结构。
F# 模块Microsoft.FSharp.Collections.List具有列表上的常见操作。然而,F# 会自动导入该模块,并使其可供每个 F# 应用程序访问。
创建并初始化列表
以下是创建列表的各种方法 -
使用列表文字。
使用cons (::) 运算符。
使用List模块的List.init方法。
使用一些称为列表推导式的语法结构。
列表文字
在此方法中,您只需在方括号中指定以分号分隔的值序列。例如 -
let list1 = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
缺点 (::) 运算符
使用此方法,您可以使用 :: 运算符将一些值添加到现有列表中或添加到现有列表中。例如 -
let list2 = 1::2::3::4::5::6::7::8::9::10::[];;
[] 表示空列表。
列出初始化方法
List 模块的 List.init 方法通常用于创建列表。该方法的类型为 -
val init : int -> (int -> 'T) -> 'T list
第一个参数是新列表的所需长度,第二个参数是初始化函数,用于生成列表中的项目。
例如,
let list5 = List.init 5 (fun index -> (index, index * index, index * index * index))
这里,索引函数生成列表。
列表推导式
列表推导式是用于生成列表的特殊语法结构。
F# 列表理解语法有两种形式:范围和生成器。
范围具有以下结构 - [start .. end] 和 [start .. step .. end]
例如,
let list3 = [1 .. 10]
生成器具有以下构造 - [for x in collection do ... yield expr]
例如,
let list6 = [ for a in 1 .. 10 do yield (a * a) ]
当yield关键字将单个值推入列表时,关键字yield!将值的集合推入列表。
以下函数演示了上述方法 -
例子
(* using list literals *) let list1 = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10] printfn "The list: %A" list1 (*using cons operator *) let list2 = 1 :: 2 :: 3 :: [] printfn "The list: %A" list2 (* using range constructs*) let list3 = [1 .. 10] printfn "The list: %A" list3 (* using range constructs *) let list4 = ['a' .. 'm'] printfn "The list: %A" list4 (* using init method *) let list5 = List.init 5 (fun index -> (index, index * index, index * index * index)) printfn "The list: %A" list5 (* using yield operator *) let list6 = [ for a in 1 .. 10 do yield (a * a) ] printfn "The list: %A" list6 (* using yield operator *) let list7 = [ for a in 1 .. 100 do if a % 3 = 0 && a % 5 = 0 then yield a] printfn "The list: %A" list7 (* using yield! operator *) let list8 = [for a in 1 .. 3 do yield! [ a .. a + 3 ] ] printfn "The list: %A" list8
当您编译并执行该程序时,它会产生以下输出 -
The list: [1; 2; 3; 4; 5; 6; 7; 8; 9; 10] The list: [1; 2; 3] The list: [1; 2; 3; 4; 5; 6; 7; 8; 9; 10] The list: ['a'; 'b'; 'c'; 'd'; 'e'; 'f'; 'g'; 'h'; 'i'; 'j'; 'k'; 'l'; 'm'] The list: [(0, 0, 0); (1, 1, 1); (2, 4, 8); (3, 9, 27); (4, 16, 64)] The list: [1; 4; 9; 16; 25; 36; 49; 64; 81; 100] The list: [15; 30; 45; 60; 75; 90] The list: [1; 2; 3; 4; 2; 3; 4; 5; 3; 4; 5; 6]
列表数据类型的属性
下表显示了列表数据类型的各种属性 -
财产 | 类型 | 描述 |
---|---|---|
头 | 'T | 第一个元素。 |
空的 | 'T 列表 | 返回适当类型的空列表的静态属性。 |
是空的 | 布尔值 | 如果列表没有元素,则为true 。 |
物品 | 'T | 指定索引处的元素(从零开始)。 |
长度 | 整数 | 元素的数量。 |
尾巴 | 'T 列表 | 没有第一个元素的列表。 |
以下示例显示了这些属性的使用 -
例子
let list1 = [ 2; 4; 6; 8; 10; 12; 14; 16 ] // Use of Properties printfn "list1.IsEmpty is %b" (list1.IsEmpty) printfn "list1.Length is %d" (list1.Length) printfn "list1.Head is %d" (list1.Head) printfn "list1.Tail.Head is %d" (list1.Tail.Head) printfn "list1.Tail.Tail.Head is %d" (list1.Tail.Tail.Head) printfn "list1.Item(1) is %d" (list1.Item(1))
当您编译并执行该程序时,它会产生以下输出 -
list1.IsEmpty is false list1.Length is 8 list1.Head is 2 list1.Tail.Head is 4 list1.Tail.Tail.Head is 6 list1.Item(1) is 4
列表中的基本运算符
下表显示了列表数据类型的基本操作 -
价值 | 描述 |
---|---|
追加 : 'T 列表 → 'T 列表 → 'T 列表 | 返回一个新列表,其中包含第一个列表的元素,后跟第二个列表的元素。 |
平均值:'T 列表 → ^T | 返回列表中元素的平均值。 |
平均:('T → ^U) → 'T 列表 → ^U | 返回通过将函数应用于列表的每个元素而生成的元素的平均值。 |
选择:('T→'U选项)→'T列表→'U列表 | 将给定函数应用于列表的每个元素。返回由函数返回Some的每个元素的结果组成的列表。 |
收集:('T→'U列表)→'T列表→'U列表 | 对于列表中的每个元素,应用给定的函数。连接所有结果并返回组合列表。 |
concat : seq<'T 列表> → 'T 列表 | 返回一个新列表,其中按顺序包含每个列表的元素。 |
空:'T 列表 | 返回给定类型的空列表。 |
存在:('T → bool) → 'T 列表 → bool | 测试列表中的任何元素是否满足给定的谓词。 |
存在2:('T1→'T2→布尔)→'T1列表→'T2列表→布尔 | 测试列表中任意一对对应元素是否满足给定谓词。 |
过滤器:('T→布尔)→'T列表→'T列表 | 返回一个新集合,仅包含给定谓词返回true的集合元素。 |
查找:('T→布尔)→'T列表→'T | 返回给定函数返回true的第一个元素。 |
findIndex : ('T → bool) → 'T 列表 → int | 返回列表中满足给定谓词的第一个元素的索引。 |
折叠 : ('状态 → 'T → '状态) → '状态 → 'T 列表 → '状态 | 将函数应用于集合的每个元素,通过计算线程化累加器参数。该函数采用第二个参数,并将该函数应用于它和列表的第一个元素。然后,它将这个结果与第二个元素一起传递到函数中,依此类推。最后返回最终结果。如果输入函数为 f 并且元素为 i0...iN,则此函数计算 f (... (fs i0) i1 ...) iN。 |
Fold2 : ('状态→'T1→'T2→'状态)→'状态→'T1列表→'T2列表→'状态 | 将函数应用于两个集合的相应元素,通过计算线程化累加器参数。这些集合必须具有相同的大小。如果输入函数为 f 并且元素为 i0...iN 和 j0...jN,则此函数计算 f (... (fs i0 j0)...) iN jN。 |
FoldBack : ('T → '状态 → '状态) → 'T 列表 → '状态 → '状态 | 将函数应用于集合的每个元素,通过计算线程化累加器参数。如果输入函数为 f 并且元素为 i0...iN,则计算 f i0 (...(f iN s))。 |
FoldBack2 : ('T1 → 'T2 → '状态 → '状态) → 'T1 列表 → 'T2 列表 → '状态 → '状态 | 将函数应用于两个集合的相应元素,通过计算线程化累加器参数。这些集合必须具有相同的大小。如果输入函数为 f 并且元素为 i0...iN 和 j0...jN,则此函数计算 f i0 j0 (...(f iN jN s))。 |
forall : ('T → bool) → 'T 列表 → bool | 测试集合的所有元素是否满足给定的谓词。 |
forall2 : ('T1 → 'T2 → bool) → 'T1 列表 → 'T2 列表 → bool | 测试集合中所有对应元素是否成对满足给定谓词。 |
头 : 'T 列表 → 'T | 返回列表的第一个元素。 |
init : int → (int → 'T) → 'T 列表 | 通过在每个索引上调用给定的生成器来创建列表。 |
isEmpty : 'T 列表 → bool | 如果列表不包含元素,则返回true ,否则返回false。 |
iter : ('T → 单位) → 'T 列表 → 单位 | 将给定函数应用于集合的每个元素。 |
iter2 : ('T1 → 'T2 → 单元) → 'T1 列表 → 'T2 列表 → 单元 | 同时将给定函数应用于两个集合。集合必须具有相同的大小。 |
iteri : (int → 'T → 单位) → 'T 列表 → 单位 | 将给定函数应用于集合的每个元素。传递给函数的整数表示元素的索引。 |
iteri2 : (int → 'T1 → 'T2 → 单位) → 'T1 列表 → 'T2 列表 → 单位 | 同时将给定函数应用于两个集合。集合必须具有相同的大小。传递给函数的整数表示元素的索引。 |
长度 : 'T 列表→ int | 返回列表的长度。 |
映射:('T → 'U) → 'T 列表 → 'U 列表 | 创建一个新集合,其元素是将给定函数应用于该集合的每个元素的结果。 |
map2 : ('T1 → 'T2 → 'U) → 'T1 列表 → 'T2 列表 → 'U 列表 | 创建一个新集合,其元素是将给定函数成对应用于两个集合的相应元素的结果。 |
map3 : ('T1 → 'T2 → 'T3 → 'U) → 'T1 列表 → 'T2 列表 → 'T3 列表 → 'U 列表 | 创建一个新集合,其元素是将给定函数同时应用于三个集合的相应元素的结果。 |
mapi : (int → 'T → 'U) → 'T 列表 → 'U 列表 | 创建一个新集合,其元素是将给定函数应用于该集合的每个元素的结果。传递给函数的整数索引表示正在转换的元素的索引(从 0 开始)。 |
mapi2 : (int → 'T1 → 'T2 → 'U) → 'T1 列表 → 'T2 列表 → 'U 列表 | 与 List.mapi 类似,但映射两个长度相等的列表中的相应元素。 |
最大值:'T 列表 → 'T | 返回列表中所有元素中最大的元素,并使用 Operators.max 进行比较。 |
maxBy : ('T → 'U) → 'T 列表 → 'T | 返回列表中所有元素中最大的元素,通过对函数结果使用 Operators.max 进行比较。 |
分钟:'T 列表→'T | 使用 Operators.min 进行比较,返回列表中所有元素中最低的元素。 |
minBy : ('T → 'U) → 'T 列表 → 'T | 返回列表中所有元素中最低的元素,通过对函数结果使用 Operators.min 进行比较 |
第 n 个 : 'T 列表 → int → 'T | 列表中的索引。第一个元素的索引为 0。 |
ofArray : 'T[] → 'T 列表 | 从给定数组创建一个列表。 |
ofSeq : seq<'T> → 'T 列表 | 从给定的可枚举对象创建一个新列表。 |
分区 : ('T → bool) → 'T 列表 * 'T 列表 | 将集合拆分为两个集合,其中包含给定谓词分别返回true和false的元素。 |
排列:(int → int) → 'T 列表 → 'T 列表 | 返回一个列表,其中所有元素都根据指定的排列进行排列。 |
pick : ('T → 'U 选项) → 'T 列表 → 'U | 将给定函数应用于连续元素,返回第一个结果,其中函数针对某个值返回Some。 |
减少:('T → 'T → 'T) → 'T 列表 → 'T | 将函数应用于集合的每个元素,通过计算线程化累加器参数。此函数将指定的函数应用于列表的前两个元素。然后,它将这个结果与第三个元素一起传递到函数中,依此类推。最后返回最终结果。如果输入函数为 f 并且元素为 i0...iN,则此函数计算 f (... (f i0 i1) i2 ...) iN。 |
reduceBack : ('T → 'T → 'T) → 'T 列表 → 'T | 将函数应用于集合的每个元素,通过计算线程化累加器参数。如果输入函数为 f 并且元素为 i0...iN,则该函数计算 f i0 (...(f iN-1 iN))。 |
复制 : (int → 'T → 'T 列表) | 通过在每个索引上调用给定的生成器来创建列表。 |
rev : 'T 列表 → 'T 列表 | 返回一个新列表,其中元素的顺序相反。 |
scan : ('状态→'T→'状态)→'状态→'T列表→'状态列表 | 将函数应用于集合的每个元素,通过计算线程化累加器参数。该函数采用第二个参数,并将指定的函数应用于它和列表的第一个元素。然后,它将这个结果与第二个元素一起传递到函数中,依此类推。最后返回中间结果列表和最终结果。 |
scanBack : ('T → '状态 → '状态) → 'T 列表 → '状态 → '状态列表 | 与foldBack类似,但同时返回中间结果和最终结果 |
排序:'T 列表→'T 列表 | 使用 Operators.compare 对给定列表进行排序。 |
排序依据:('T → '键) → 'T 列表 → 'T 列表 | 使用给定投影给出的键对给定列表进行排序。使用 Operators.compare 比较键。 |
sortWith : ('T → 'T → int) → 'T 列表 → 'T 列表 | 使用给定的比较函数对给定列表进行排序。 |
总和:^T 列表 → ^T | 返回列表中元素的总和。 |
sumBy : ('T → ^U) → 'T 列表 → ^U | 返回通过将函数应用于列表的每个元素而生成的结果的总和。 |
tail : 'T 列表 → 'T 列表 | 返回不带第一个元素的输入列表。 |
toArray : 'T 列表 → 'T [] | 从给定列表创建一个数组。 |
toSeq : 'T 列表 → seq<'T> | 将给定列表视为序列。 |
tryFind : ('T → bool) → 'T 列表 → 'T 选项 | 返回给定函数返回true的第一个元素。如果不存在这样的元素,则返回None 。 |
tryFindIndex : ('T → bool) → 'T 列表 → int 选项 | 返回列表中满足给定谓词的第一个元素的索引。如果不存在这样的元素,则返回None 。 |
tryPick : ('T → 'U 选项) → 'T 列表 → 'U 选项 | 将给定函数应用于连续元素,返回第一个结果,其中函数针对某个值返回Some。如果不存在这样的元素则返回None。 |
解压 : ('T1 * 'T2) 列表 → 'T1 列表 * 'T2 列表 | 将对列表拆分为两个列表。 |
unzip3 : ('T1 * 'T2 * 'T3) 列表 → 'T1 列表 * 'T2 列表 * 'T3 列表 | 将三元组列表拆分为三个列表。 |
zip : 'T1 列表 → 'T2 列表 → ('T1 * 'T2) 列表 | 将两个列表组合成一个对列表。两个列表的长度必须相等。 |
zip3 : 'T1 列表 → 'T2 列表 → 'T3 列表 → ('T1 * 'T2 * 'T3) 列表 | 将三个列表组合成一个三元组列表。这些列表必须具有相等的长度。 |
以下示例演示了上述功能的用途 -
实施例1
该程序显示递归地反转列表 -
let list1 = [ 2; 4; 6; 8; 10; 12; 14; 16 ] printfn "The original list: %A" list1 let reverse lt = let rec loop acc = function | [] -> acc | hd :: tl -> loop (hd :: acc) tl loop [] lt printfn "The reversed list: %A" (reverse list1)
当您编译并执行该程序时,它会产生以下输出 -
The original list: [2; 4; 6; 8; 10; 12; 14; 16] The reversed list: [16; 14; 12; 10; 8; 6; 4; 2]
但是,您可以使用模块的rev函数来达到相同的目的 -
let list1 = [ 2; 4; 6; 8; 10; 12; 14; 16 ] printfn "The original list: %A" list1 printfn "The reversed list: %A" (List.rev list1)
当您编译并执行该程序时,它会产生以下输出 -
The original list: [2; 4; 6; 8; 10; 12; 14; 16] The reversed list: [16; 14; 12; 10; 8; 6; 4; 2]
实施例2
该程序显示使用List.filter方法过滤列表-
let list1 = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10] printfn "The list: %A" list1 let list2 = list1 |> List.filter (fun x -> x % 2 = 0);; printfn "The Filtered list: %A" list2
当您编译并执行该程序时,它会产生以下输出 -
The list: [1; 2; 3; 4; 5; 6; 7; 8; 9; 10] The Filtered list: [2; 4; 6; 8; 10]
实施例3
List.map方法将列表从一种类型映射到另一种类型-
let list1 = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10] printfn "The list: %A" list1 let list2 = list1 |> List.map (fun x -> (x * x).ToString());; printfn "The Mapped list: %A" list2
当您编译并执行该程序时,它会产生以下输出 -
The list: [1; 2; 3; 4; 5; 6; 7; 8; 9; 10] The Mapped list: ["1"; "4"; "9"; "16"; "25"; "36"; "49"; "64"; "81"; "100"]
实施例4
List.append方法和 @ 运算符将一个列表附加到另一个列表-
let list1 = [1; 2; 3; 4; 5 ] let list2 = [6; 7; 8; 9; 10] let list3 = List.append list1 list2 printfn "The first list: %A" list1 printfn "The second list: %A" list2 printfn "The appened list: %A" list3 let lt1 = ['a'; 'b';'c' ] let lt2 = ['e'; 'f';'g' ] let lt3 = lt1 @ lt2 printfn "The first list: %A" lt1 printfn "The second list: %A" lt2 printfn "The appened list: %A" lt3
当您编译并执行该程序时,它会产生以下输出 -
The first list: [1; 2; 3; 4; 5] The second list: [6; 7; 8; 9; 10] The appened list: [1; 2; 3; 4; 5; 6; 7; 8; 9; 10] The first list: ['a'; 'b'; 'c'] The second list: ['e'; 'f'; 'g'] The appened list: ['a'; 'b'; 'c'; 'e'; 'f'; 'g']
实施例5
List.sort方法对列表进行排序。List.sum方法给出列表中元素的总和,List.average方法给出列表中元素的平均值-
let list1 = [9.0; 0.0; 2.0; -4.5; 11.2; 8.0; -10.0] printfn "The list: %A" list1 let list2 = List.sort list1 printfn "The sorted list: %A" list2 let s = List.sum list1 let avg = List.average list1 printfn "The sum: %f" s printfn "The average: %f" avg
当您编译并执行该程序时,它会产生以下输出 -
The list: [9.0; 0.0; 2.0; -4.5; 11.2; 8.0; -10.0] The sorted list: [-10.0; -4.5; 0.0; 2.0; 8.0; 9.0; 11.2] The sum: 15.700000 The average: 2.242857
“折叠”操作将函数应用于列表中的每个元素,将函数的结果聚合到累加器变量中,并将累加器作为折叠操作的结果返回。
实施例6
List.fold方法从左到右对每个元素应用函数,而List.foldBack从右到左对每个元素应用函数。
let sumList list = List.fold (fun acc elem -> acc + elem) 0 list printfn "Sum of the elements of list %A is %d." [ 1 .. 10 ] (sumList [ 1 .. 10 ])
当您编译并执行该程序时,它会产生以下输出 -
Sum of the elements of list [1; 2; 3; 4; 5; 6; 7; 8; 9; 10] is 55.