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