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.