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

序列的基本操作

下表显示了序列数据类型上的基本操作:

描述
append : seq<'T> → seq<'T> → seq<'T> 将给定的两个枚举包装为单个连接的枚举。
average : seq<^T> → ^T 返回序列中元素的平均值。
averageBy : ('T → ^U) → seq<'T> → ^U 返回通过将函数应用于序列的每个元素而生成的平均结果。
cache : seq<'T> → seq<'T> 返回与输入序列的缓存版本相对应的序列。
cast : IEnumerable → seq<'T> 将松散类型的 System.Collections 序列包装为类型化序列。
choose : ('T → 'U option) → seq<'T> → seq<'U> 将给定函数应用于列表的每个元素。返回由函数返回Some的每个元素的结果组成的列表。
collect : ('T → 'Collection) → seq<'T> → seq<'U> 将给定函数应用于序列的每个元素并将所有结果连接起来。
compareWith : ('T → 'T → int) → seq<'T> → seq<'T> → int 使用给定的比较函数逐元素比较两个序列。
concat : seq<'Collection> → seq<'T> 将给定的枚举-枚举组合为单个连接的枚举。
countBy : ('T → 'Key) → seq<'T> → seq<'Key * int> 将键生成函数应用于序列的每个元素,并返回一个序列,该序列产生唯一的键及其在原始序列中的出现次数。
delay : (unit → seq<'T>) → seq<'T> 返回一个序列,该序列由给定的序列的延迟规范构建。
distinct : seq<'T> → seq<'T> 返回一个序列,该序列根据对条目进行的通用哈希和相等性比较不包含重复条目。如果某个元素在序列中出现多次,则会丢弃后面的出现。
distinctBy : ('T → 'Key) → seq<'T> → seq<'T> 返回一个序列,该序列根据给定的键生成函数返回的键上的通用哈希和相等性比较不包含重复条目。如果某个元素在序列中出现多次,则会丢弃后面的出现。
empty : seq<'T> 创建一个空序列。
exactlyOne : seq<'T> → 'T 返回序列的唯一元素。
exists : ('T → bool) → seq<'T> → bool 测试序列的任何元素是否满足给定的谓词。
exists2 : ('T1 → 'T2 → bool) → seq<'T1> → seq<'T2> → bool 测试输入序列的任何一对对应元素是否满足给定的谓词。
filter : ('T → bool) → seq<'T> → seq<'T> 返回一个新集合,其中只包含给定谓词返回true的集合的元素。
find : ('T → bool) → seq<'T> → 'T 返回给定函数返回true的第一个元素。
findIndex : ('T → bool) → seq<'T> → int 返回给定函数返回true的第一个元素的索引。
fold : ('State → 'T → 'State) → 'State → seq<'T> → 'State 将一个函数应用于集合的每个元素,将累加器参数贯穿计算。如果输入函数是 f,元素是 i0...iN,则此函数计算 f (... (f s 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>> 将键生成函数应用于序列的每个元素,并产生唯一的键序列。每个唯一键还包含与该键匹配的所有元素的序列。
head : seq<'T> → 'T 返回序列的第一个元素。
init : int → (int → 'T) → seq<'T> 生成一个新的序列,当迭代时,通过调用给定的函数返回连续的元素,直到给定的计数。调用函数的结果不会被保存,也就是说,该函数会根据需要重新应用以重新生成元素。该函数将传递正在生成的项目的索引。
initInfinite : (int → 'T) → seq<'T> 生成一个新的序列,当迭代时,将通过调用给定的函数返回连续的元素。调用函数的结果不会被保存,也就是说,该函数将根据需要重新应用以重新生成元素。该函数将传递正在生成的项目的索引。
isEmpty : seq<'T> → bool 测试序列是否包含任何元素。
iter : ('T → unit) → seq<'T> → unit 将给定函数应用于集合的每个元素。
iter2 : ('T1 → 'T2 → unit) → seq<'T1> → seq<'T2> → unit 同时将给定函数应用于两个集合。如果一个序列比另一个序列短,则忽略较长序列的其余元素。
iteri : (int → 'T → unit) → seq<'T> → unit 将给定函数应用于集合的每个元素。传递给函数的整数表示元素的索引。
last : seq<'T> → 'T 返回序列的最后一个元素。
length : seq<'T> → int 返回序列的长度。
map : ('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 开始)。
max : seq<'T> → 'T 返回序列中所有元素中最大的元素,通过使用 Operators.max 进行比较。
maxBy : ('T → 'U) → seq<'T> → 'T 返回序列中所有元素中最大的元素,通过使用 Operators.max 对函数结果进行比较。
min : seq<'T> → 'T 返回序列中所有元素中最小的元素,通过使用 Operators.min 进行比较。
minBy : ('T → 'U) → seq<'T> → 'T 返回序列中所有元素中最小的元素,通过使用 Operators.min 对函数结果进行比较。
nth : int → seq<'T> → 'T 计算集合中的第n个元素。
ofArray : 'T array → seq<'T> 将给定的数组视为序列。
ofList : 'T list → seq<'T> 将给定的列表视为序列。
pairwise : seq<'T> → seq<'T * 'T> 返回输入序列中每个元素及其前驱的序列,第一个元素除外,它只作为第二个元素的前驱返回。
pick : ('T → 'U option) → seq<'T> → 'U 将给定函数应用于连续元素,返回函数返回Some值的第一个值。
readonly : seq<'T> → seq<'T> 创建一个新的序列对象,该对象委托给给定的序列对象。这确保了原始序列不能通过类型转换被重新发现和更改。例如,如果给定一个数组,返回的序列将返回数组的元素,但是您不能将返回的序列对象转换为数组。
reduce : ('T → 'T → 'T) → seq<'T> → 'T 将一个函数应用于序列的每个元素,将累加器参数贯穿计算。首先将函数应用于前两个元素。然后将此结果与第三个元素一起提供给函数,依此类推。返回最终结果。
scan : ('State → 'T → 'State) → 'State → seq<'T> → seq<'State> 类似于 Seq.fold,但按需计算并返回中间结果和最终结果的序列。
singleton : 'T → seq<'T> 返回一个只产生一个项目的序列。
skip : int → seq<'T> → seq<'T> 返回一个序列,该序列跳过底层序列的指定数量的元素,然后产生序列的其余元素。
skipWhile : ('T → bool) → seq<'T> → seq<'T> 返回一个序列,当迭代时,跳过底层序列的元素,直到给定的谓词返回true,然后产生序列的其余元素。
sort : seq<'T> → seq<'T> 生成一个按键排序的序列。
sortBy : ('T → 'Key) → seq<'T> → seq<'T> 将一个键生成函数应用于序列的每个元素,并生成一个按键排序的序列。键的比较使用由 Operators.compare 实现的泛型比较。
sum : seq<^T> → ^T 返回序列中元素的总和。
sumBy 返回将函数应用于序列的每个元素后生成的各个结果的总和。
take : int → seq<'T> → seq<'T> 返回序列中从开头开始指定数量的元素。
takeWhile : ('T → bool) → seq<'T> → seq<'T> 返回一个序列,在迭代时,只要给定的谓词返回 **true**,就产生基础序列的元素,然后不再返回任何元素。
toArray : seq<'T> → 'T[] 从给定集合创建一个数组。
toList : seq<'T> → 'T list 从给定集合创建一个列表。
truncate : int → seq<'T> → seq<'T> 返回一个序列,在枚举时最多返回指定数量的元素。
tryFind : ('T → bool) → seq<'T> → 'T option 返回给定函数返回 **true** 的第一个元素,如果不存在这样的元素,则返回 **None**。
tryFindIndex : ('T → bool) → seq<'T> → int option 返回序列中第一个满足给定谓词的元素的索引,如果不存在这样的元素,则返回 **None**。
tryPick : ('T → 'U option) → seq<'T> → 'U option 将给定函数应用于连续元素,返回函数返回Some值的第一个值。
unfold : ('State → 'T * 'State option) → 'State → seq<'T> 返回一个包含由给定计算生成的元素的序列。
where : ('T → bool) → seq<'T> → seq<'T> 返回一个新集合,其中只包含给定谓词返回 **true** 的集合元素。它是 Seq.filter 的同义词。
windowed : 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
广告
© . All rights reserved.