F # - Sequenze

Le sequenze, come gli elenchi, rappresentano anche una raccolta ordinata di valori. Tuttavia, gli elementi in una sequenza o un'espressione di sequenza vengono calcolati quando richiesto. Non vengono calcolati contemporaneamente e per questo motivo vengono utilizzati per rappresentare strutture dati infinite.

Definizione di sequenze

Le sequenze vengono definite utilizzando la seguente sintassi:

seq { expr }

Per esempio,

let seq1 = seq { 1 .. 10 }

Creazione di sequenze ed espressioni di sequenze

Analogamente agli elenchi, puoi creare sequenze utilizzando intervalli e comprensioni.

Le espressioni di sequenza sono le espressioni che puoi scrivere per creare sequenze. Questi possono essere fatti -

  • Specificando l'intervallo.
  • Specificando l'intervallo con incremento o decremento.
  • Utilizzando il yield parola chiave per produrre valori che diventano parte della sequenza.
  • Utilizzando l'operatore →.

I seguenti esempi dimostrano il concetto:

Esempio 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

Quando compili ed esegui il programma, restituisce il seguente output:

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

Esempio 2

Il seguente programma stampa i numeri primi da 1 a 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

Quando compili ed esegui il programma, restituisce il seguente output:

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

Operazioni di base sulla sequenza

La tabella seguente mostra le operazioni di base sul tipo di dati della sequenza:

Valore Descrizione
aggiungi: seq <'T> → seq <' T> → seq <'T> Avvolge le due enumerazioni date come un'unica enumerazione concatenata.
media: seq <^ T> → ^ T Restituisce la media degli elementi nella sequenza.
averageBy: ('T → ^ U) → seq <' T> → ^ U Restituisce la media dei risultati generati applicando la funzione a ogni elemento della sequenza.
cache: seq <'T> → seq <' T> Restituisce una sequenza che corrisponde a una versione memorizzata nella cache della sequenza di input.
cast: IEnumerable → seq <'T> Avvolge un sistema a bassa tipizzazione. Sequenza di raccolte come sequenza digitata.
scegli: (opzione 'T →' U) → seq <'T> → seq <' U> Applica la funzione data a ogni elemento dell'elenco. Restituisce l'elenco composto dai risultati per ogni elemento in cui restituisce la funzioneSome.
collect: ('T →' Collection) → seq <'T> → seq <' U> Applica la funzione data a ciascun elemento della sequenza e concatena tutti i risultati.
compareCon: ('T →' T → int) → seq <'T> → seq <' T> → int Confronta due sequenze utilizzando la funzione di confronto data, elemento per elemento.
concat: seq <'Collection> → seq <' T> Combina l'enumerazione di enumerazioni data come una singola enumerazione concatenata.
countBy: ('T →' Key) → seq <'T> → seq <' Key * int> Applica una funzione di generazione di chiavi a ogni elemento di una sequenza e restituisce una sequenza che fornisce chiavi univoche e il loro numero di occorrenze nella sequenza originale.
ritardo: (unità → seq <'T>) → seq <' T> Restituisce una sequenza costruita dalla specifica ritardata data di una sequenza.
distinto: seq <'T> → seq <' T> Restituisce una sequenza che non contiene voci duplicate in base a hash generici e confronti di uguaglianza sulle voci. Se un elemento si verifica più volte nella sequenza, le occorrenze successive vengono eliminate.
distintoBy: ('T →' Key) → seq <'T> → seq <' T> Restituisce una sequenza che non contiene voci duplicate in base all'hash generico e ai confronti di uguaglianza sulle chiavi restituite dalla funzione di generazione della chiave specificata. Se un elemento si verifica più volte nella sequenza, le occorrenze successive vengono eliminate.
vuoto: seq <'T> Crea una sequenza vuota.
esattamente Uno: seq <'T> →' T Restituisce l'unico elemento della sequenza.
esiste: ('T → bool) → seq <' T> → bool Verifica se qualsiasi elemento della sequenza soddisfa il predicato dato.
esiste2: ('T1 →' T2 → bool) → seq <'T1> → seq <' T2> → bool Verifica se una coppia di elementi corrispondenti delle sequenze di input soddisfa il predicato dato.
filtro: ('T → bool) → seq <' T> → seq <'T> Restituisce una nuova raccolta contenente solo gli elementi della raccolta per cui restituisce il predicato specificato true.
trova: ('T → bool) → seq <' T> → 'T Restituisce il primo elemento per il quale restituisce la funzione data true.
findIndex: ('T → bool) → seq <' T> → int Restituisce l'indice del primo elemento per il quale restituisce la funzione data true.
fold: ('State →' T → 'State) →' State → seq <'T> →' State Applica una funzione a ogni elemento della raccolta, inserendo un argomento dell'accumulatore attraverso il calcolo. Se la funzione di input è f e gli elementi sono i0 ... iN, questa funzione calcola f (... (fs i0) ...) iN.
forall: ('T → bool) → seq <' T> → bool Verifica se tutti gli elementi della sequenza soddisfano il predicato dato.
forall2: ('T1 →' T2 → bool) → seq <'T1> → seq <' T2> → bool Verifica che tutte le coppie di elementi estratti dalle due sequenze soddisfino il predicato dato. Se una sequenza è più breve dell'altra, gli elementi rimanenti della sequenza più lunga vengono ignorati.
groupBy: ('T →' Key) → seq <'T> → seq <' Key * seq <'T >> Applica una funzione di generazione di chiavi a ogni elemento di una sequenza e produce una sequenza di chiavi univoche. Ogni chiave univoca contiene anche una sequenza di tutti gli elementi che corrispondono a questa chiave.
head: seq <'T> →' T Restituisce il primo elemento della sequenza.
init: int → (int → 'T) → seq <' T> Genera una nuova sequenza che, una volta iterata, restituisce elementi successivi chiamando la funzione data, fino al conteggio dato. I risultati della chiamata della funzione non vengono salvati, ovvero la funzione viene riapplicata se necessario per rigenerare gli elementi. Alla funzione viene passato l'indice dell'elemento generato.
initInfinite: (int → 'T) → seq <' T> Genera una nuova sequenza che, una volta iterata, restituirà elementi successivi chiamando la funzione data. I risultati della chiamata della funzione non vengono salvati, ovvero la funzione verrà riapplicata se necessario per rigenerare gli elementi. Alla funzione viene passato l'indice dell'elemento generato.
isEmpty: seq <'T> → bool Verifica se una sequenza contiene elementi.
iter: ('T → unit) → seq <' T> → unit Applica la funzione data a ogni elemento della raccolta.
iter2: ('T1 →' T2 → unit) → seq <'T1> → seq <' T2> → unit Applica la funzione data a due raccolte contemporaneamente. Se una sequenza è più breve dell'altra, gli elementi rimanenti della sequenza più lunga vengono ignorati.
iteri: (int → 'T → unit) → seq <' T> → unit Applica la funzione data a ogni elemento della raccolta. L'intero passato alla funzione indica l'indice dell'elemento.
ultimo: seq <'T> →' T Restituisce l'ultimo elemento della sequenza.
lunghezza: seq <'T> → int Restituisce la lunghezza della sequenza.
mappa: ('T →' U) → seq <'T> → seq <' U> Crea una nuova raccolta i cui elementi sono il risultato dell'applicazione della funzione data a ciascuno degli elementi della raccolta. La funzione data verrà applicata quando gli elementi vengono richiesti utilizzando il metodo MoveNext sugli enumeratori recuperati dall'oggetto.
map2: ('T1 →' T2 → 'U) → seq <' T1> → seq <'T2> → seq <' U> Crea una nuova raccolta i cui elementi sono il risultato dell'applicazione della funzione data alle coppie di elementi corrispondenti dalle due sequenze. Se una sequenza di input è più breve dell'altra, gli elementi rimanenti della sequenza più lunga vengono ignorati.
mapi: (int → 'T →' U) → seq <'T> → seq <' U> Crea una nuova raccolta i cui elementi sono il risultato dell'applicazione della funzione data a ciascuno degli elementi della raccolta. L'indice intero passato alla funzione indica l'indice (da 0) dell'elemento trasformato.
max: seq <'T> →' T Restituisce il più grande di tutti gli elementi della sequenza, confrontato utilizzando Operators.max.
maxBy: ('T →' U) → seq <'T> →' T Restituisce il più grande di tutti gli elementi della sequenza, confrontato utilizzando Operators.max sul risultato della funzione.
min: seq <'T> →' T Restituisce il più basso di tutti gli elementi della sequenza, confrontato utilizzando Operators.min.
minBy: ('T →' U) → seq <'T> →' T Restituisce il più basso di tutti gli elementi della sequenza, confrontato utilizzando Operators.min sul risultato della funzione.
ennesimo: int → seq <'T> →' T Calcola l' ennesimo elemento nella raccolta.
ofArray: 'T array → seq <' T> Visualizza l'array dato come una sequenza.
ofList: 'T list → seq <' T> Visualizza l'elenco fornito come una sequenza.
a coppie: seq <'T> → seq <' T * 'T> Restituisce una sequenza di ogni elemento nella sequenza di input e del suo predecessore, ad eccezione del primo elemento che viene restituito solo come predecessore del secondo elemento.
scegli: (opzione 'T →' U) → seq <'T> →' U Applica la funzione data a elementi successivi, restituendo il primo valore in cui la funzione restituisce a Some valore.
sola lettura: seq <'T> → seq <' T> Crea un nuovo oggetto sequenza che delega all'oggetto sequenza specificato. Ciò garantisce che la sequenza originale non possa essere riscoperta e modificata da un cast di tipo. Ad esempio, se viene fornito un array, la sequenza restituita restituirà gli elementi dell'array, ma non è possibile eseguire il cast dell'oggetto sequenza restituito su un array.
ridurre: ('T →' T → 'T) → seq <' T> → 'T Applica una funzione a ogni elemento della sequenza, inserendo un argomento dell'accumulatore attraverso il calcolo. Inizia applicando la funzione ai primi due elementi. Quindi inserisci questo risultato nella funzione insieme al terzo elemento e così via. Restituisci il risultato finale.
scansione: ('State →' T → 'State) →' State → seq <'T> → seq <' State> Come Seq. Piega, ma calcola su richiesta e restituisce la sequenza dei risultati intermedi e finali.
singleton: 'T → seq <' T> Restituisce una sequenza che produce un solo elemento.
salta: int → seq <'T> → seq <' T> Restituisce una sequenza che salta un numero specificato di elementi della sequenza sottostante e quindi restituisce gli elementi rimanenti della sequenza.
skipWhile: ('T → bool) → seq <' T> → seq <'T> Restituisce una sequenza che, quando iterata, salta gli elementi della sequenza sottostante mentre il predicato dato ritorna true, e quindi restituisce gli elementi rimanenti della sequenza.
ordina: seq <'T> → seq <' T> Restituisce una sequenza ordinata per chiavi.
sortBy: ('T →' Key) → seq <'T> → seq <' T> Applica una funzione di generazione di chiavi a ogni elemento di una sequenza e produce una sequenza ordinata per chiavi. Le chiavi vengono confrontate utilizzando il confronto generico implementato da Operators.compare.
somma: seq <^ T> → ^ T Restituisce la somma degli elementi nella sequenza.
sumBy Restituisce la somma dei risultati generati applicando la funzione a ogni elemento della sequenza.
prendere: int → seq <'T> → seq <' T> Restituisce i primi elementi della sequenza fino a un conteggio specificato.
takeWhile: ('T → bool) → seq <' T> → seq <'T> Restituisce una sequenza che, quando iterata, restituisce elementi della sequenza sottostante mentre il predicato dato ritorna true, e quindi non restituisce ulteriori elementi.
toArray: seq <'T> →' T [] Crea un array dalla raccolta data.
toList: seq <'T> →' T list Crea un elenco dalla raccolta data.
troncare: int → seq <'T> → seq <' T> Restituisce una sequenza che, se enumerata, non restituisce più di un numero specificato di elementi.
tryFind: ('T → bool) → seq <' T> → 'T opzione Restituisce il primo elemento per il quale restituisce la funzione data true, o None se tale elemento non esiste.
tryFindIndex: ('T → bool) → seq <' T> → int opzione Restituisce l'indice del primo elemento nella sequenza che soddisfa il predicato dato, o None se tale elemento non esiste.
tryPick: (opzione 'T →' U) → seq <'T> → opzione' U Applica la funzione data a elementi successivi, restituendo il primo valore in cui la funzione restituisce a Some valore.
unfold: ('State →' T * 'State opzione) →' State → seq <'T> Restituisce una sequenza che contiene gli elementi generati dal dato calcolo.
dove: ('T → bool) → seq <' T> → seq <'T> Restituisce una nuova raccolta contenente solo gli elementi della raccolta per cui restituisce il predicato specificato true. Un sinonimo di Seq.filter.
windowed: int → seq <'T> → seq <' T []> Restituisce una sequenza che produce finestre scorrevoli di elementi contenenti disegnati dalla sequenza di input. Ogni finestra viene restituita come un nuovo array.
zip: seq <'T1> → seq <' T2> → seq <'T1 *' T2> Combina le due sequenze in un elenco di coppie. Non è necessario che le due sequenze abbiano la stessa lunghezza: quando una sequenza è esaurita, tutti gli elementi rimanenti nell'altra sequenza vengono ignorati.
zip3: seq <'T1> → seq <' T2> → seq <'T3> → seq <' T1 * 'T2 *' T3> Combina le tre sequenze in un elenco di triple. Non è necessario che le sequenze abbiano la stessa lunghezza: quando una sequenza è esaurita, tutti gli elementi rimanenti nelle altre sequenze vengono ignorati.

I seguenti esempi dimostrano gli usi di alcune delle funzionalità di cui sopra:

Esempio 1

Questo programma crea una sequenza vuota e la riempie in seguito -

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

Quando compili ed esegui il programma, restituisce il seguente output:

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

Si prega di notare che -

  • Il metodo Seq.empty crea una sequenza vuota.

  • Il metodo Seq.singleton crea una sequenza di un solo elemento specificato.

  • Il metodo Seq.init crea una sequenza per la quale vengono creati gli elementi utilizzando una determinata funzione.

  • I metodi Seq.ofArray e Seq.ofList <'T> creano sequenze da array ed elenchi.

  • Il metodo Seq.iter consente di iterare attraverso una sequenza.

Esempio 2

Il metodo Seq.unfold genera una sequenza da una funzione di calcolo che assume uno stato e lo trasforma per produrre ogni elemento successivo nella sequenza.

La seguente funzione produce i primi 20 numeri naturali:

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

Quando compili ed esegui il programma, restituisce il seguente output:

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

Esempio 3

Il metodo Seq.truncate crea una sequenza da un'altra sequenza, ma limita la sequenza a un numero di elementi specificato.

Il metodo Seq.take crea una nuova sequenza che contiene un numero specificato di elementi dall'inizio di una sequenza.

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

Quando compili ed esegui il programma, restituisce il seguente output:

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