- 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# - 序列
序列(如列表)也表示值的有序集合。但是,会在需要时计算序列或序列表达式中的元素。它们不是立即计算的,因此它们被用来表示无限的数据结构。
定义序列
序列使用以下语法定义 -
seq { expr }
例如,
let seq1 = seq { 1 .. 10 }
创建序列和序列表达式
与列表类似,您可以使用范围和推导式创建序列。
序列表达式是您可以为创建序列而编写的表达式。这些可以做到 -
- 通过指定范围。
- 通过指定递增或递减的范围。
- 通过使用yield关键字来生成成为序列一部分的值。
- 通过使用 → 运算符。
以下示例演示了这个概念 -
实施例1
(* Sequences *) let seq1 = seq { 1 .. 10 } (* ascending order and increment*) printfn "The Sequence: %A" seq1 let seq2 = seq { 1 .. 5 .. 50 } (* descending order and decrement*) printfn "The Sequence: %A" seq2 let seq3 = seq {50 .. -5 .. 0} printfn "The Sequence: %A" seq3 (* using yield *) let seq4 = seq { for a in 1 .. 10 do yield a, a*a, a*a*a } printfn "The Sequence: %A" seq4
当您编译并执行该程序时,它会产生以下输出 -
The Sequence: seq [1; 2; 3; 4; ...] The Sequence: seq [1; 6; 11; 16; ...] The Sequence: seq [50; 45; 40; 35; ...] The Sequence: seq [(1, 1, 1); (2, 4, 8); (3, 9, 27); (4, 16, 64); ...]
实施例2
以下程序打印从 1 到 50 的质数 -
(* Recursive isprime function. *) let isprime n = let rec check i = i > n/2 || (n % i <> 0 && check (i + 1)) check 2 let primeIn50 = seq { for n in 1..50 do if isprime n then yield n } for x in primeIn50 do printfn "%d" x
当您编译并执行该程序时,它会产生以下输出 -
1 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47
序列的基本操作
下表显示了序列数据类型的基本操作 -
价值 | 描述 |
---|---|
追加 : seq<'T> → seq<'T> → seq<'T> | 将两个给定的枚举包装为单个串联枚举。 |
平均值:seq<^T> → ^T | 返回序列中元素的平均值。 |
平均:('T → ^U) → seq<'T> → ^U | 返回通过将函数应用于序列的每个元素而生成的结果的平均值。 |
缓存:seq<'T> → seq<'T> | 返回与输入序列的缓存版本相对应的序列。 |
强制转换:IEnumerable → seq<'T> | 包装松散类型的系统。作为类型化序列的集合序列。 |
选择:('T → 'U 选项)→ seq<'T> → seq<'U> | 将给定函数应用于列表的每个元素。返回由函数返回Some的每个元素的结果组成的列表。 |
收集 : ('T → '集合) → seq<'T> → seq<'U> | 将给定函数应用于序列的每个元素并连接所有结果。 |
比较:('T → 'T → int) → seq<'T> → seq<'T> → int | 使用给定的比较函数逐个元素地比较两个序列。 |
concat : seq<'集合> → seq<'T> | 将给定的枚举组合为单个串联枚举。 |
countBy : ('T → 'Key) → seq<'T> → seq<'Key * int> | 将键生成函数应用于序列的每个元素,并返回一个序列,生成唯一键及其在原始序列中出现的次数。 |
延迟 : (单位 → seq<'T>) → seq<'T> | 返回根据给定的序列延迟规范构建的序列。 |
不同:seq<'T> → seq<'T> | 根据条目上的通用哈希和相等比较,返回不包含重复条目的序列。如果一个元素在序列中出现多次,则后面出现的元素将被丢弃。 |
uniqueBy : ('T → 'Key) → seq<'T> → seq<'T> | 根据给定键生成函数返回的键的通用散列和相等比较,返回不包含重复条目的序列。如果一个元素在序列中出现多次,则后面出现的元素将被丢弃。 |
空:seq<'T> | 创建一个空序列。 |
正好一个:seq<'T> → 'T | 返回序列的唯一元素。 |
存在:('T → bool) → seq<'T> → bool | 测试序列的任何元素是否满足给定的谓词。 |
存在 2 : ('T1 → 'T2 → bool) → seq<'T1> → seq<'T2> → bool | 测试输入序列的任何一对对应元素是否满足给定的谓词。 |
过滤器:('T → bool) → seq<'T> → seq<'T> | 返回一个新集合,仅包含给定谓词返回true的集合元素。 |
查找:('T → bool) → seq<'T> → 'T | 返回给定函数返回true的第一个元素。 |
findIndex : ('T → bool) → seq<'T> → int | 返回给定函数返回true的第一个元素的索引。 |
折叠 : ('状态 → 'T → '状态) → '状态 → seq<'T> → '状态 | 将函数应用于集合的每个元素,通过计算线程化累加器参数。如果输入函数为 f 并且元素为 i0...iN,则此函数计算 f (... (fs i0)...) iN。 |
forall : ('T → bool) → seq<'T> → bool | 测试序列的所有元素是否满足给定的谓词。 |
forall2 : ('T1 → 'T2 → bool) → seq<'T1> → seq<'T2> → bool | 测试从两个序列中提取的所有元素对满足给定的谓词。如果一个序列比另一个序列短,则较长序列的剩余元素将被忽略。 |
groupBy : ('T → 'Key) → seq<'T> → seq<'Key * seq<'T>> | 将键生成函数应用于序列的每个元素并生成唯一键的序列。每个唯一键还包含与该键匹配的所有元素的序列。 |
头 : seq<'T> → 'T | 返回序列的第一个元素。 |
init : int → (int → 'T) → seq<'T> | 生成一个新序列,该序列在迭代时通过调用给定函数返回连续元素,直到给定计数。调用该函数的结果不会被保存,即根据需要重新应用该函数以重新生成元素。该函数传递正在生成的项目的索引。 |
initInfinite : (int → 'T) → seq<'T> | 生成一个新序列,该序列在迭代时将通过调用给定函数返回连续元素。调用该函数的结果不会被保存,也就是说,该函数将根据需要重新应用以重新生成元素。该函数传递正在生成的项目的索引。 |
isEmpty : seq<'T> → bool | 测试序列是否包含任何元素。 |
iter : ('T → 单位) → seq<'T> → 单位 | 将给定函数应用于集合的每个元素。 |
iter2 : ('T1 → 'T2 → 单位) → seq<'T1> → seq<'T2> → 单位 | 同时将给定函数应用于两个集合。如果一个序列比另一个序列短,则较长序列的剩余元素将被忽略。 |
iteri : (int → 'T → 单位) → seq<'T> → 单位 | 将给定函数应用于集合的每个元素。传递给函数的整数表示元素的索引。 |
最后:seq<'T> → 'T | 返回序列的最后一个元素。 |
长度:seq<'T> → int | 返回序列的长度。 |
映射:('T → 'U) → seq<'T> → seq<'U> | 创建一个新集合,其元素是将给定函数应用于该集合的每个元素的结果。当需要使用从对象检索的枚举器上的 MoveNext 方法的元素时,将应用给定的函数。 |
map2 : ('T1 → 'T2 → 'U) → seq<'T1> → seq<'T2> → seq<'U> | 创建一个新集合,其元素是将给定函数应用于两个序列中相应元素对的结果。如果一个输入序列比另一个短,则忽略较长序列的剩余元素。 |
mapi : (int → 'T → 'U) → seq<'T> → seq<'U> | 创建一个新集合,其元素是将给定函数应用于该集合的每个元素的结果。传递给函数的整数索引表示正在转换的元素的索引(从 0 开始)。 |
最大值:seq<'T> → 'T | 返回序列中所有元素中最大的元素,并使用 Operators.max 进行比较。 |
maxBy : ('T → 'U) → seq<'T> → 'T | 返回序列中所有元素中最大的元素,通过对函数结果使用 Operators.max 进行比较。 |
分钟:seq<'T> → 'T | 使用 Operators.min 进行比较,返回序列中所有元素中最低的元素。 |
minBy : ('T → 'U) → seq<'T> → 'T | 返回序列中所有元素中最低的元素,通过对函数结果使用 Operators.min 进行比较。 |
第 n 个:int → seq<'T> → 'T | 计算集合中的第 n 个元素。 |
ofArray : 'T 数组 → seq<'T> | 将给定数组视为序列。 |
ofList : 'T 列表 → seq<'T> | 将给定列表视为序列。 |
成对 : seq<'T> → seq<'T * 'T> | 返回输入序列中每个元素及其前任元素的序列,但第一个元素除外,它仅作为第二个元素的前任返回。 |
pick : ('T → 'U 选项) → seq<'T> → 'U | 将给定函数应用于连续元素,返回函数返回Some值的第一个值。 |
只读:seq<'T> → seq<'T> | 创建一个委托给给定序列对象的新序列对象。这确保了原始序列不能被类型转换重新发现和改变。例如,如果给定一个数组,则返回的序列将返回该数组的元素,但不能将返回的序列对象强制转换为数组。 |
减少:('T → 'T → 'T) → seq<'T> → 'T | 将函数应用于序列的每个元素,并通过计算线程化累加器参数。首先将该函数应用于前两个元素。然后将此结果与第三个元素一起输入到函数中,依此类推。返回最终结果。 |
扫描:('状态→'T→'状态)→'状态→seq<'T>→seq<'状态> | 与 Seq.fold 类似,但按需计算并返回中间结果和最终结果的序列。 |
单例:'T → seq<'T> | 返回仅产生一项的序列。 |
跳过:int → seq<'T> → seq<'T> | 返回一个序列,该序列跳过基础序列的指定数量的元素,然后生成序列的剩余元素。 |
SkipWhile : ('T → bool) → seq<'T> → seq<'T> | 返回一个序列,在迭代时,当给定谓词返回true时,该序列会跳过基础序列的元素,然后生成序列的剩余元素。 |
排序:seq<'T> → seq<'T> | 产生按键排序的序列。 |
排序依据:('T → 'Key) → seq<'T> → seq<'T> | 将键生成函数应用于序列的每个元素并生成按键排序的序列。使用 Operators.compare 实现的通用比较来比较键。 |
总和:seq<^T> → ^T | 返回序列中元素的总和。 |
总和 | 返回将函数应用于序列的每个元素所生成的结果的总和。 |
取:int → seq<'T> → seq<'T> | 返回序列的第一个元素,最多达到指定的计数。 |
takeWhile : ('T → bool) → seq<'T> → seq<'T> | 返回一个序列,该序列在迭代时生成基础序列的元素,同时给定谓词返回true,然后不再返回任何元素。 |
toArray : seq<'T> → 'T[] | 从给定集合创建一个数组。 |
toList : seq<'T> → 'T 列表 | 从给定的集合创建一个列表。 |
截断:int → seq<'T> → seq<'T> | 返回一个序列,在枚举时返回不超过指定数量的元素。 |
tryFind : ('T → bool) → seq<'T> → 'T 选项 | 返回给定函数返回 true 的第一个元素,如果不存在这样的元素,则返回None 。 |
tryFindIndex : ('T → bool) → seq<'T> → int 选项 | 返回序列中满足给定谓词的第一个元素的索引,如果不存在这样的元素,则返回None 。 |
tryPick : ('T → 'U 选项) → seq<'T> → 'U 选项 | 将给定函数应用于连续元素,返回函数返回Some值的第一个值。 |
展开 : ('状态 → 'T * '状态选项) → '状态 → seq<'T> | 返回一个序列,其中包含给定计算生成的元素。 |
其中:('T → bool) → seq<'T> → seq<'T> | 返回一个新集合,仅包含给定谓词返回true的集合元素。Seq.filter 的同义词。 |
窗口化:int → seq<'T> → seq<'T []> | 返回一个序列,该序列产生包含从输入序列中提取的元素的滑动窗口。每个窗口都作为新数组返回。 |
zip : seq<'T1> → seq<'T2> → seq<'T1 * 'T2> | 将两个序列组合成一个对的列表。两个序列不需要具有相同的长度 - 当一个序列耗尽时,另一个序列中的任何剩余元素都将被忽略。 |
zip3 : seq<'T1> → seq<'T2> → seq<'T3> → seq<'T1 * 'T2 * 'T3> | 将三个序列组合成三元组列表。序列不需要具有相同的长度 - 当一个序列耗尽时,其他序列中的任何剩余元素都将被忽略。 |
以下示例演示了上述一些功能的用法 -
实施例1
该程序创建一个空序列并稍后填充它 -
(* Creating sequences *) let emptySeq = Seq.empty let seq1 = Seq.singleton 20 printfn"The singleton sequence:" printfn "%A " seq1 printfn"The init sequence:" let seq2 = Seq.init 5 (fun n -> n * 3) Seq.iter (fun i -> printf "%d " i) seq2 printfn"" (* converting an array to sequence by using cast *) printfn"The array sequence 1:" let seq3 = [| 1 .. 10 |] :> seq<int> Seq.iter (fun i -> printf "%d " i) seq3 printfn"" (* converting an array to sequence by using Seq.ofArray *) printfn"The array sequence 2:" let seq4 = [| 2..2.. 20 |] |> Seq.ofArray Seq.iter (fun i -> printf "%d " i) seq4 printfn""
当您编译并执行该程序时,它会产生以下输出 -
The singleton sequence: seq [20] The init sequence: 0 3 6 9 12 The array sequence 1: 1 2 3 4 5 6 7 8 9 10 The array sequence 2: 2 4 6 8 10 12 14 16 18 20
请注意 -
Seq.empty 方法创建一个空序列。
Seq.singleton 方法创建仅包含一个指定元素的序列。
Seq.init 方法创建一个序列,其中的元素是使用给定函数创建的。
Seq.ofArray 和 Seq.ofList<'T> 方法从数组和列表创建序列。
Seq.iter 方法允许迭代序列。
实施例2
Seq.unfold 方法从计算函数生成一个序列,该函数采用一个状态并将其转换以生成序列中的每个后续元素。
以下函数生成前 20 个自然数 -
let seq1 = Seq.unfold (fun state -> if (state > 20) then None else Some(state, state + 1)) 0 printfn "The sequence seq1 contains numbers from 0 to 20." for x in seq1 do printf "%d " x printfn" "
当您编译并执行该程序时,它会产生以下输出 -
The sequence seq1 contains numbers from 0 to 20. 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
实施例3
Seq.truncate 方法从另一个序列创建一个序列,但将该序列限制为指定数量的元素。
Seq.take 方法创建一个新序列,其中包含从序列开头算起的指定数量的元素。
let mySeq = seq { for i in 1 .. 10 -> 3*i } let truncatedSeq = Seq.truncate 5 mySeq let takeSeq = Seq.take 5 mySeq printfn"The original sequence" Seq.iter (fun i -> printf "%d " i) mySeq printfn"" printfn"The truncated sequence" Seq.iter (fun i -> printf "%d " i) truncatedSeq printfn"" printfn"The take sequence" Seq.iter (fun i -> printf "%d " i) takeSeq printfn""
当您编译并执行该程序时,它会产生以下输出 -
The original sequence 3 6 9 12 15 18 21 24 27 30 The truncated sequence 3 6 9 12 15 The take sequence 3 6 9 12 15