当前位置: 首页 > 文档资料 > F# 中文教程 >

F# - 序列( Sequences)

优质
小牛编辑
121浏览
2023-12-01

序列,如列表也表示有序的值集合。 但是,在需要时计算序列或序列表达式中的元素。 它们不是一次计算的,因此它们用于表示无限的数据结构。

定义序列

序列使用以下语法定义 -

seq { expr }

例如,

let seq1 = seq { 1 .. 10 }

创建序列和序列表达式

与列表类似,您可以使用范围和理解来创建序列。

序列表达式是您可以编写用于创建序列的表达式。 这些可以做到 -

  • By specifying the range.
  • 通过增加或减少指定范围。
  • 通过使用yield关键字生成成为序列一部分的值。
  • 使用→运算符。

以下示例演示了这一概念 -

例子1 (Example 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 (Example 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 →seq →seq将两个给定的枚举包装为单个连接枚举。
平均值:seq →^ T.返回序列中元素的平均值。
averageBy:('T→^ U)→seq →^ U.返回通过将函数应用于序列的每个元素而生成的结果的平均值。
cache:seq →seq返回与输入序列的缓存版本对应的序列。
cast:IEnumerable→seq包装松散类型的系统。 集合序列为类型序列。
选择:('T→'U选项)→seq →seq将给定函数应用于列表的每个元素。 返回由函数返回Some每个元素的结果组成的列表。
收集:('T→'收藏)→seq →seq将给定函数应用于序列的每个元素并连接所有结果。
compareWith:('T→'T→int)→seq →seq →int使用给定的比较函数逐个元素地比较两个序列。
concat:seq →seq将给定的枚举枚举组合为单个连接枚举。
countBy:('T→'Key)→seq →seq将键生成函数应用于序列的每个元素,并返回一个序列,生成唯一键及其在原始序列中出现的次数。
延迟:(单位→seq )→seq返回根据给定的序列延迟规范构建的序列。
distinct:seq →seq根据条目上的泛型哈希和相等比较,返回不包含重复条目的序列。 如果元素在序列中多次出现,则丢弃后面出现的事件。
distinctBy :('T→'Key)→seq →seq根据给定密钥生成函数返回的键上的泛型哈希和相等比较,返回不包含重复条目的序列。 如果元素在序列中多次出现,则丢弃后面出现的事件。
empty : seq<'T>Creates an empty sequence.
exactOne:seq →'T返回序列的唯一元素。
存在:('T→bool)→seq →布尔测试序列中的任何元素是否满足给定谓词。
exists2:('T1→'T2→bool)→seq →seq →bool测试输入序列的任何一对相应元素是否满足给定谓词。
filter:('T→bool)→seq →seq返回一个新集合,该集合仅包含给定谓词返回true的集合元素。
找到:('T→bool)→seq →'T返回给定函数返回true的第一个元素。
findIndex:('T→bool)→seq →int返回给定函数返回true的第一个元素的索引。
fold:('State→'T→'State)→'State→seq →'State将函数应用于集合的每个元素,通过计算线程化累加器参数。 如果输入函数是f并且元素是i0 ... iN,则此函数计算f(...(fs i0)...)iN。
forall:('T→bool)→seq →bool测试序列的所有元素是否满足给定谓词。
forall2:('T1→'T2→bool)→seq →seq →bool测试从两个序列中提取的所有元素对满足给定的谓词。 如果一个序列比另一个序列短,则忽略较长序列的其余元素。
groupBy:('T→'Key)→seq →seq >将键生成函数应用于序列的每个元素,并生成一系列唯一键。 每个唯一键还包含与此键匹配的所有元素的序列。
head:seq →'T返回序列的第一个元素。
init:int→(int→'T)→seq生成一个新序列,当迭代时,通过调用给定函数返回连续元素,直到给定计数。 调用函数的结果不会被保存,也就是说,根据需要重新应用函数来重新生成元素。 该函数传递正在生成的项的索引。
initInfinite:(int→'T)→seq生成一个新序列,当迭代时,将通过调用给定函数返回连续元素。 调用该函数的结果不会被保存,也就是说,将根据需要重新应用该函数以重新生成元素。 该函数传递正在生成的项的索引。
isEmpty:seq →布尔测试序列是否包含任何元素。
iter :('T→单位)→seq →单位将给定函数应用于集合的每个元素。
iter2:('T1→'T2→单位)→seq →seq →单位将给定函数同时应用于两个集合。 如果一个序列比另一个序列短,则忽略较长序列的其余元素。
iteri:(int→'T→unit)→seq →unit将给定函数应用于集合的每个元素。 传递给函数的整数表示元素的索引。
最后:seq →'T返回序列的最后一个元素。
length:seq →int返回序列的长度。
map:('T→'U)→seq →seq创建一个新集合,其元素是将给定函数应用于集合的每个元素的结果。 在从对象检索的枚举数中使用MoveNext方法需要元素时,将应用给定的函数。
map2:('T1→'T2→'U)→seq →seq →seq创建一个新集合,其元素是将给定函数应用于两个序列中相应元素对的结果。 如果一个输入序列比另一个输入序列短,则忽略较长序列的其余元素。
mapi:(int→'T→'U)→seq →seq创建一个新集合,其元素是将给定函数应用于集合的每个元素的结果。 传递给函数的整数索引表示正在转换的元素的索引(从0开始)。
max:seq →'T返回序列中所有元素中最大的元素,使用Operators.max进行比较。
maxBy :('T→'U)→seq →'T返回序列中所有元素中最大的元素,通过在函数结果上使用Operators.max进行比较。
min:seq →'T返回序列中所有元素的最低元素,使用Operators.min进行比较。
minBy :('T→'U)→seq →'T返回序列中所有元素的最低元素,通过在函数结果上使用Operators.min进行比较。
nth:int→seq →'T计算集合中的nth元素。
ofArray:'T array→seq将给定数组视为序列。
ofList:'T list→seq将给定列表视为序列。
成对:seq →seq返回输入序列及其前一个元素中每个元素的序列,但第一个元素除外,它仅作为第二个元素的前任返回。
选择:('T→'U选项)→seq →'U将给定函数应用于连续元素,返回函数返回Some值的第一个值。
readonly:seq →seq创建一个委托给定序列对象的新序列对象。 这确保了原型序列不能被类型转换重新发现和改变。 例如,如果给定一个数组,则返回的序列将返回数组的元素,但是您无法将返回的序列对象强制转换为数组。
reduce:('T→'T→'T)→seq →'T将函数应用于序列的每个元素,通过计算线程化累加器参数。 首先将函数应用于前两个元素。 然后将此结果与第三个元素一起提供给函数,依此类推。 返回最终结果。
scan:('State→'T→'State)→'State→seq →seq与Seq.fold一样,但是按需计算并返回中间和最终结果的序列。
单身人士:'T→seq返回仅生成一个项目的序列。
skip:int→seq →seq返回跳过基础序列的指定数量元素的序列,然后生成序列的其余元素。
skipWhile :('T→bool)→seq →seq返回一个序列,当迭代时,在给定谓词返回true,时跳过基础序列的元素true,然后生成序列的其余元素。
sort:seq →seq产生按键排序的序列。
sortBy:('T→'Key)→seq →seq将键生成函数应用于序列的每个元素,并生成按键排序的序列。 使用Operators.compare实现的通用比较来比较密钥。
sum:seq →^ T.返回序列中元素的总和。
sumBy返回通过将函数应用于序列的每个元素而生成的结果的总和。
take:int→seq →seq返回序列的第一个元素,直到指定的计数。
takeWhile :('T→bool)→seq →seq返回一个序列,当迭代时,在给定谓词返回true,时生成基础序列的元素true,然后不再返回其他元素。
toArray:seq →'T []从给定集合创建数组。
toList:seq →'T列表从给定集合创建列表。
truncate:int→seq →seq返回枚举时返回的序列不超过指定数量的元素的序列。
tryFind:('T→bool)→seq →'T选项返回给定函数返回true,的第一个元素,如果不存在此元素,则返回None
tryFindIndex :('T→bool)→seq →int选项返回满足给定谓词的序列中第一个元素的索引,如果不存在此类元素,则返回None
tryPick :('T→'U选项)→seq →'U选项将给定函数应用于连续元素,返回函数返回Some值的第一个值。
展开:('州→'T *'州选项)→'州→seq返回包含给定计算生成的元素的序列。
其中:('T→bool)→seq →seq返回一个新集合,该集合仅包含给定谓词返回true的集合元素。 Seq.filter的同义词。
windowed:int→seq →seq返回一个序列,该序列生成包含从输入序列中提取的元素的滑动窗口。 每个窗口都以新数组的形式返回。
zip:seq →seq →seq将两个序列组合成一对列表。 这两个序列不需要具有相同的长度 - 当一个序列耗尽时,忽略另一个序列中的任何剩余元素。
zip3:seq →seq →seq →seq将三个序列组合成三元组列表。 序列不需要具有相等的长度 - 当一个序列耗尽时,忽略其他序列中的任何剩余元素。

以下示例演示了上述某些功能的用途 -

例子1 (Example 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 方法从数组和列表创建序列。

  • Seq.iter方法允许迭代序列。

例子2 (Example 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 (Example 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