F # - sekwencje

Sekwencje, podobnie jak listy, również reprezentują uporządkowany zbiór wartości. Jednak elementy w sekwencji lub wyrażeniu sekwencji są obliczane, gdy jest to wymagane. Nie są obliczane od razu iz tego powodu są używane do reprezentowania nieskończonych struktur danych.

Definiowanie sekwencji

Sekwencje są definiowane przy użyciu następującej składni -

seq { expr }

Na przykład,

let seq1 = seq { 1 .. 10 }

Tworzenie sekwencji i wyrażeń sekwencji

Podobnie jak w przypadku list, możesz tworzyć sekwencje przy użyciu zakresów i wyrażeń.

Wyrażenia sekwencji to wyrażenia, które można napisać w celu tworzenia sekwencji. Można to zrobić -

  • Określając zakres.
  • Określając zakres ze zwiększaniem lub zmniejszaniem.
  • Korzystając z yield słowo kluczowe, aby uzyskać wartości, które staną się częścią sekwencji.
  • Używając operatora →.

Poniższe przykłady ilustrują koncepcję -

Przykład 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

Kiedy kompilujesz i wykonujesz program, daje to następujące dane wyjściowe -

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); ...]

Przykład 2

Poniższy program wypisuje liczby pierwsze od 1 do 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

Kiedy kompilujesz i wykonujesz program, daje to następujące dane wyjściowe -

1
2
3
5
7
11
13
17
19
23
29
31
37
41
43
47

Podstawowe operacje na sekwencji

W poniższej tabeli przedstawiono podstawowe operacje na sekwencjach typu danych -

Wartość Opis
append: seq <'T> → seq <' T> → seq <'T> Zawija dwa podane wyliczenia jako pojedyncze połączone wyliczenie.
średnia: seq <^ T> → ^ T Zwraca średnią elementów w sekwencji.
średnia Przez: ('T → ^ U) → seq <' T> → ^ U Zwraca średnią wyników wygenerowanych przez zastosowanie funkcji do każdego elementu sekwencji.
cache: seq <'T> → seq <' T> Zwraca sekwencję, która odpowiada zbuforowanej wersji sekwencji wejściowej.
cast: IEnumerable → seq <'T> Zawija luźno wpisany System. Sekwencja kolekcji jako sekwencja wpisana.
wybierz: (opcja 'T →' U) → seq <'T> → seq <' U> Stosuje daną funkcję do każdego elementu listy. Zwróć listę zawierającą wyniki dla każdego elementu, z którego funkcja zwracaSome.
collect: ('T →' Collection) → seq <'T> → seq <' U> Stosuje daną funkcję do każdego elementu sekwencji i łączy wszystkie wyniki.
porównaj Z: ('T →' T → int) → seq <'T> → seq <' T> → int Porównuje dwie sekwencje przy użyciu podanej funkcji porównania, element po elemencie.
concat: seq <'Collection> → seq <' T> Łączy podane wyliczenia jako pojedyncze połączone wyliczenie.
countBy: ('T →' Key) → seq <'T> → seq <' Key * int> Stosuje funkcję generującą klucz do każdego elementu sekwencji i zwraca sekwencję dającą unikatowe klucze i ich liczbę wystąpień w oryginalnej sekwencji.
opóźnienie: (jednostka → seq <'T>) → seq <' T> Zwraca sekwencję utworzoną na podstawie podanej opóźnionej specyfikacji sekwencji.
odrębny: seq <'T> → seq <' T> Zwraca sekwencję, która nie zawiera zduplikowanych wpisów zgodnie z ogólnymi porównaniami skrótów i równości wpisów. Jeśli element występuje wiele razy w sekwencji, późniejsze wystąpienia są odrzucane.
odrębnyBy: (klawisz 'T →') → seq <'T> → seq <' T> Zwraca sekwencję, która nie zawiera zduplikowanych wpisów zgodnie z ogólnym skrótem i porównaniami równości kluczy zwróconych przez daną funkcję generującą klucz. Jeśli element występuje wiele razy w sekwencji, późniejsze wystąpienia są odrzucane.
pusty: seq <'T> Tworzy pustą sekwencję.
dokładnie jeden: seq <'T> →' T Zwraca jedyny element sekwencji.
istnieje: ('T → bool) → seq <' T> → bool Sprawdza, czy jakikolwiek element ciągu spełnia podany predykat.
istnieje2: ('T1 →' T2 → bool) → seq <'T1> → seq <' T2> → bool Sprawdza, czy jakakolwiek para odpowiednich elementów sekwencji wejściowych spełnia podany predykat.
filter: ('T → bool) → seq <' T> → seq <'T> Zwraca nową kolekcję zawierającą tylko elementy kolekcji, dla których zwraca dany predykat true.
znajdź: ('T → bool) → seq <' T> → 'T Zwraca pierwszy element, dla którego zwraca dana funkcja true.
findIndex: ('T → bool) → seq <' T> → int Zwraca indeks pierwszego elementu, dla którego zwraca dana funkcja true.
fold: ('Stan →' T → 'Stan) →' Stan → sekwencja <'T> →' Stan Stosuje funkcję do każdego elementu kolekcji, tworząc wątek argumentu akumulatora przez obliczenia. Jeśli funkcja wejściowa to f, a elementy to i0 ... iN, to ta funkcja oblicza f (... (fs i0) ...) iN.
forall: ('T → bool) → seq <' T> → bool Sprawdza, czy wszystkie elementy ciągu spełniają podany predykat.
forall2: ('T1 →' T2 → bool) → seq <'T1> → seq <' T2> → bool Testuje wszystkie pary elementów narysowanych z dwóch sekwencji, które spełniają zadany predykat. Jeśli jedna sekwencja jest krótsza od drugiej, pozostałe elementy dłuższej sekwencji są ignorowane.
groupBy: ('T →' Key) → seq <'T> → seq <' Key * seq <'T >> Stosuje funkcję generującą klucz do każdego elementu sekwencji i zwraca sekwencję unikatowych kluczy. Każdy unikalny klucz zawiera również sekwencję wszystkich elementów, które pasują do tego klucza.
head: seq <'T> →' T Zwraca pierwszy element sekwencji.
init: int → (int → 'T) → seq <' T> Generuje nową sekwencję, która po wykonaniu iteracji zwraca kolejne elementy, wywołując daną funkcję, aż do podanej liczby. Wyniki wywołania funkcji nie są zapisywane, to znaczy funkcja jest ponownie stosowana w razie potrzeby w celu ponownego wygenerowania elementów. Funkcja otrzymuje indeks generowanego elementu.
initInfinite: (int → 'T) → seq <' T> Generuje nową sekwencję, która po wykonaniu iteracji zwróci kolejne elementy, wywołując daną funkcję. Wyniki wywołania funkcji nie są zapisywane, to znaczy funkcja zostanie ponownie zastosowana w razie potrzeby do ponownego wygenerowania elementów. Funkcja otrzymuje indeks generowanego elementu.
isEmpty: seq <'T> → bool Sprawdza, czy sekwencja ma jakieś elementy.
iter: ('T → unit) → seq <' T> → unit Stosuje daną funkcję do każdego elementu kolekcji.
iter2: ('T1 →' T2 → unit) → seq <'T1> → seq <' T2> → unit Stosuje daną funkcję do dwóch kolekcji jednocześnie. Jeśli jedna sekwencja jest krótsza od drugiej, pozostałe elementy dłuższej sekwencji są ignorowane.
iteri: (int → 'T → unit) → seq <' T> → unit Stosuje daną funkcję do każdego elementu kolekcji. Liczba całkowita przekazana do funkcji wskazuje indeks elementu.
ostatnia: seq <'T> →' T Zwraca ostatni element sekwencji.
length: seq <'T> → int Zwraca długość sekwencji.
map: ('T →' U) → seq <'T> → seq <' U> Tworzy nową kolekcję, której elementy są wynikiem zastosowania danej funkcji do każdego z elementów kolekcji. Podana funkcja zostanie zastosowana, gdy elementy są żądane przy użyciu metody MoveNext na modułach wyliczających pobranych z obiektu.
map2: ('T1 →' T2 → 'U) → seq <' T1> → seq <'T2> → seq <' U> Tworzy nową kolekcję, której elementy są wynikiem zastosowania danej funkcji do odpowiednich par elementów z dwóch sekwencji. Jeśli jedna sekwencja wejściowa jest krótsza od drugiej, pozostałe elementy dłuższej sekwencji są ignorowane.
mapi: (int → 'T →' U) → seq <'T> → seq <' U> Tworzy nową kolekcję, której elementy są wynikiem zastosowania danej funkcji do każdego z elementów kolekcji. Indeks w postaci liczby całkowitej przekazany do funkcji wskazuje indeks (od 0) transformowanego elementu.
max: seq <'T> →' T Zwraca największy ze wszystkich elementów sekwencji w porównaniu przy użyciu Operators.max.
maxBy: ('T →' U) → seq <'T> →' T Zwraca największy ze wszystkich elementów sekwencji w porównaniu przy użyciu Operators.max w wyniku funkcji.
min: seq <'T> →' T Zwraca najniższy ze wszystkich elementów sekwencji w porównaniu przy użyciu Operators.min.
min By: ('T →' U) → seq <'T> →' T Zwraca najniższy ze wszystkich elementów sekwencji w porównaniu przy użyciu Operators.min w wyniku funkcji.
nth: int → seq <'T> →' T Oblicza n-ty element w kolekcji.
ofArray: 'T array → seq <' T> Wyświetla daną tablicę jako sekwencję.
ofList: 'T lista → seq <' T> Wyświetla podaną listę jako sekwencję.
parami: seq <'T> → seq <' T * 'T> Zwraca sekwencję każdego elementu w sekwencji wejściowej i jego poprzednika, z wyjątkiem pierwszego elementu, który jest zwracany tylko jako poprzednik drugiego elementu.
wybierz: (opcja 'T →' U) → seq <'T> →' U Stosuje daną funkcję do kolejnych elementów, zwracając pierwszą wartość, gdy funkcja zwraca Some wartość.
readonly: seq <'T> → seq <' T> Tworzy nowy obiekt sekwencji, który jest delegowany do danego obiektu sekwencji. Dzięki temu oryginalna sekwencja nie może zostać ponownie odkryta i zmutowana przez rzutowanie typu. Na przykład, jeśli dana jest tablica, zwrócona sekwencja zwróci elementy tablicy, ale nie można rzutować zwróconego obiektu sekwencji na tablicę.
zmniejszyć: ('T →' T → 'T) → seq <' T> → 'T Stosuje funkcję do każdego elementu sekwencji, tworząc wątek argumentu akumulatora przez obliczenia. Zacznij od zastosowania funkcji do pierwszych dwóch elementów. Następnie wprowadź ten wynik do funkcji wraz z trzecim elementem i tak dalej. Zwróć wynik końcowy.
skanowanie: ('Stan →' T → 'Stan) →' Stan → seq <'T> → seq <' Stan> Podobnie jak Seq.fold, ale oblicza na żądanie i zwraca sekwencję wyników pośrednich i końcowych.
singleton: 'T → seq <' T> Zwraca sekwencję, która daje tylko jeden element.
skip: int → seq <'T> → seq <' T> Zwraca sekwencję, która pomija określoną liczbę elementów sekwencji podstawowej, a następnie zwraca pozostałe elementy sekwencji.
skipWhile: ('T → bool) → seq <' T> → seq <'T> Zwraca sekwencję, która po wykonaniu iteracji pomija elementy sekwencji bazowej, gdy dany predykat zwraca true, a następnie zwraca pozostałe elementy sekwencji.
sort: seq <'T> → seq <' T> Podaje sekwencję uporządkowaną według kluczy.
sortBy: ('T →' Key) → seq <'T> → seq <' T> Stosuje funkcję generującą klucz do każdego elementu sekwencji i zwraca sekwencję uporządkowaną według kluczy. Klucze są porównywane przy użyciu porównania ogólnego zaimplementowanego przez Operators.compare.
suma: seq <^ T> → ^ T Zwraca sumę elementów w sekwencji.
sumBy Zwraca sumę wyników wygenerowanych przez zastosowanie funkcji do każdego elementu sekwencji.
take: int → seq <'T> → seq <' T> Zwraca pierwsze elementy sekwencji do określonej liczby.
takeWhile: ('T → bool) → seq <' T> → seq <'T> Zwraca sekwencję, która po wykonaniu iteracji daje elementy sekwencji bazowej, podczas gdy dany predykat zwraca true, a następnie nie zwraca żadnych dalszych elementów.
toArray: seq <'T> →' T [] Tworzy tablicę z podanej kolekcji.
toList: seq <'T> →' T list Tworzy listę z podanej kolekcji.
truncate: int → seq <'T> → seq <' T> Zwraca sekwencję, która po wyliczeniu zwraca nie więcej niż określoną liczbę elementów.
tryFind: ('T → bool) → seq <' T> → 'T opcja Zwraca pierwszy element, dla którego zwraca dana funkcja true, lub None jeśli taki element nie istnieje.
tryFindIndex: ('T → bool) → seq <' T> → int opcja Zwraca indeks pierwszego elementu w sekwencji, który spełnia podany predykat lub None jeśli taki element nie istnieje.
tryPick: (opcja 'T →' U) → seq <'T> → opcja' U Stosuje daną funkcję do kolejnych elementów, zwracając pierwszą wartość, gdy funkcja zwraca Some wartość.
unfold: ('Stan →' T * 'opcja stanu) →' Stan → sekwencja <'T> Zwraca sekwencję zawierającą elementy wygenerowane przez dane obliczenie.
gdzie: ('T → bool) → seq <' T> → seq <'T> Zwraca nową kolekcję zawierającą tylko elementy kolekcji, dla których zwraca dany predykat true. Synonim dla Seq.filter.
windowed: int → seq <'T> → seq <' T []> Zwraca sekwencję, która daje przesuwane okna zawierające elementy narysowane z sekwencji wejściowej. Każde okno jest zwracane jako nowa tablica.
zip: seq <'T1> → seq <' T2> → seq <'T1 *' T2> Łączy dwie sekwencje w listę par. Te dwie sekwencje nie muszą mieć równych długości - gdy jedna sekwencja jest wyczerpana, wszystkie pozostałe elementy w drugiej sekwencji są ignorowane.
zip3: seq <'T1> → seq <' T2> → seq <'T3> → seq <' T1 * 'T2 *' T3> Łączy trzy sekwencje w listę trójek. Sekwencje nie muszą mieć równych długości - gdy jedna sekwencja jest wyczerpana, wszelkie pozostałe elementy w innych sekwencjach są ignorowane.

Poniższe przykłady pokazują zastosowania niektórych z powyższych funkcji -

Przykład 1

Ten program tworzy pustą sekwencję i wypełnia ją później -

(* 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""

Kiedy kompilujesz i wykonujesz program, daje to następujące dane wyjściowe -

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

Należy pamiętać, że -

  • Metoda Seq.empty tworzy pustą sekwencję.

  • Metoda Seq.singleton tworzy sekwencję tylko jednego określonego elementu.

  • Metoda Seq.init tworzy sekwencję, dla której tworzone są elementy przy użyciu danej funkcji.

  • Metody Seq.ofArray i Seq.ofList <'T> tworzą sekwencje z tablic i list.

  • Metoda Seq.iter umożliwia iterację sekwencji.

Przykład 2

Metoda Seq.unfold generuje sekwencję z funkcji obliczeniowej, która przyjmuje stan i przekształca go w celu utworzenia każdego kolejnego elementu w sekwencji.

Poniższa funkcja daje pierwsze 20 liczb naturalnych -

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" "

Kiedy kompilujesz i wykonujesz program, daje to następujące dane wyjściowe -

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

Przykład 3

Metoda Seq.truncate tworzy sekwencję z innej sekwencji, ale ogranicza sekwencję do określonej liczby elementów.

Metoda Seq.take tworzy nową sekwencję zawierającą określoną liczbę elementów od początku sekwencji.

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""

Kiedy kompilujesz i wykonujesz program, daje to następujące dane wyjściowe -

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