F # - Séquences

Les séquences, comme les listes, représentent également une collection ordonnée de valeurs. Cependant, les éléments d'une séquence ou d'une expression de séquence sont calculés lorsque cela est nécessaire. Ils ne sont pas calculés à la fois, et pour cette raison, ils sont utilisés pour représenter des structures de données infinies.

Définition de séquences

Les séquences sont définies à l'aide de la syntaxe suivante -

seq { expr }

Par exemple,

let seq1 = seq { 1 .. 10 }

Création d'expressions de séquences et de séquences

Comme pour les listes, vous pouvez créer des séquences à l'aide de plages et de compréhensions.

Les expressions de séquence sont les expressions que vous pouvez écrire pour créer des séquences. Celles-ci peuvent être faites -

  • En spécifiant la plage.
  • En spécifiant la plage avec incrémentation ou décrémentation.
  • En utilisant le yield mot-clé pour produire des valeurs qui font partie de la séquence.
  • En utilisant l'opérateur →.

Les exemples suivants illustrent le concept -

Exemple 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

Lorsque vous compilez et exécutez le programme, il produit la sortie suivante -

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

Exemple 2

Le programme suivant imprime les nombres premiers de 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

Lorsque vous compilez et exécutez le programme, il produit la sortie suivante -

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

Opérations de base sur séquence

Le tableau suivant montre les opérations de base sur le type de données de séquence -

Valeur La description
ajouter: seq <'T> → seq <' T> → seq <'T> Entoure les deux énumérations données en une seule énumération concaténée.
moyenne: seq <^ T> → ^ T Renvoie la moyenne des éléments de la séquence.
averageBy: ('T → ^ U) → seq <' T> → ^ U Renvoie la moyenne des résultats générés en appliquant la fonction à chaque élément de la séquence.
cache: seq <'T> → seq <' T> Renvoie une séquence qui correspond à une version mise en cache de la séquence d'entrée.
cast: IEnumerable → seq <'T> Enveloppe un système de typage lâche. Séquence de collections sous forme de séquence typée.
choisissez: (option 'T →' U) → seq <'T> → seq <' U> Applique la fonction donnée à chaque élément de la liste. Renvoie la liste composée des résultats pour chaque élément où la fonction retourneSome.
collect: ('T →' Collection) → seq <'T> → seq <' U> Applique la fonction donnée à chaque élément de la séquence et concatène tous les résultats.
compareWith: ('T →' T → int) → seq <'T> → seq <' T> → int Compare deux séquences à l'aide de la fonction de comparaison donnée, élément par élément.
concat: seq <'Collection> → seq <' T> Combine l'énumération d'énumérations donnée en une seule énumération concaténée.
countBy: (touche 'T →') → seq <'T> → seq <' Key * int> Applique une fonction de génération de clé à chaque élément d'une séquence et renvoie une séquence produisant des clés uniques et leur nombre d'occurrences dans la séquence d'origine.
délai: (unité → seq <'T>) → seq <' T> Renvoie une séquence construite à partir de la spécification différée donnée d'une séquence.
distinct: seq <'T> → seq <' T> Renvoie une séquence qui ne contient aucune entrée en double selon des comparaisons génériques de hachage et d'égalité sur les entrées. Si un élément apparaît plusieurs fois dans la séquence, les dernières occurrences sont supprimées.
distinctBy: (touche 'T →') → seq <'T> → seq <' T> Renvoie une séquence qui ne contient aucune entrée en double selon les comparaisons génériques de hachage et d'égalité sur les clés renvoyées par la fonction de génération de clé donnée. Si un élément apparaît plusieurs fois dans la séquence, les dernières occurrences sont supprimées.
vide: seq <'T> Crée une séquence vide.
exactementOne: seq <'T> →' T Renvoie le seul élément de la séquence.
existe: ('T → bool) → seq <' T> → bool Teste si un élément de la séquence satisfait le prédicat donné.
existe2: ('T1 →' T2 → booléen) → seq <'T1> → seq <' T2> → bool Teste si une paire d'éléments correspondants des séquences d'entrée satisfait le prédicat donné.
filtre: ('T → booléen) → seq <' T> → seq <'T> Renvoie une nouvelle collection contenant uniquement les éléments de la collection pour lesquels le prédicat donné retourne true.
find: ('T → booléen) → seq <' T> → 'T Renvoie le premier élément pour lequel la fonction donnée renvoie true.
findIndex: ('T → booléen) → seq <' T> → int Renvoie l'index du premier élément pour lequel la fonction donnée renvoie true.
fold: ('State →' T → 'State) →' State → seq <'T> →' State Applique une fonction à chaque élément de la collection, en enfilant un argument d'accumulateur dans le calcul. Si la fonction d'entrée est f et les éléments sont i0 ... iN, alors cette fonction calcule f (... (fs i0) ...) iN.
forall: ('T → bool) → seq <' T> → bool Teste si tous les éléments de la séquence satisfont au prédicat donné.
forall2: ('T1 →' T2 → booléen) → seq <'T1> → seq <' T2> → bool Teste toutes les paires d'éléments tirés des deux séquences satisfont au prédicat donné. Si une séquence est plus courte que l'autre, les éléments restants de la séquence plus longue sont ignorés.
groupBy: (Touche 'T →') → seq <'T> → seq <' Touche * seq <'T >> Applique une fonction de génération de clé à chaque élément d'une séquence et produit une séquence de clés uniques. Chaque clé unique contient également une séquence de tous les éléments correspondant à cette clé.
tête: seq <'T> →' T Renvoie le premier élément de la séquence.
init: int → (int → 'T) → seq <' T> Génère une nouvelle séquence qui, lorsqu'elle est itérée, retourne des éléments successifs en appelant la fonction donnée, jusqu'au nombre donné. Les résultats de l'appel de la fonction ne sont pas enregistrés, c'est-à-dire que la fonction est réappliquée si nécessaire pour régénérer les éléments. La fonction reçoit l'index de l'élément en cours de génération.
initInfinite: (int → 'T) → seq <' T> Génère une nouvelle séquence qui, une fois itérée, retournera des éléments successifs en appelant la fonction donnée. Les résultats de l'appel de la fonction ne sont pas enregistrés, c'est-à-dire que la fonction sera réappliquée si nécessaire pour régénérer les éléments. La fonction reçoit l'index de l'élément en cours de génération.
isEmpty: seq <'T> → booléen Teste si une séquence contient des éléments.
iter: ('T → unité) → seq <' T> → unité Applique la fonction donnée à chaque élément de la collection.
iter2: ('T1 →' T2 → unité) → seq <'T1> → seq <' T2> → unité Applique la fonction donnée à deux collections simultanément. Si une séquence est plus courte que l'autre, les éléments restants de la séquence plus longue sont ignorés.
iteri: (int → 'T → unité) → seq <' T> → unité Applique la fonction donnée à chaque élément de la collection. L'entier passé à la fonction indique l'index de l'élément.
dernier: seq <'T> →' T Renvoie le dernier élément de la séquence.
longueur: seq <'T> → int Renvoie la longueur de la séquence.
carte: ('T →' U) → seq <'T> → seq <' U> Crée une nouvelle collection dont les éléments sont les résultats de l'application de la fonction donnée à chacun des éléments de la collection. La fonction donnée sera appliquée au fur et à mesure que les éléments sont demandés à l'aide de la méthode MoveNext sur les énumérateurs récupérés de l'objet.
map2: ('T1 →' T2 → 'U) → seq <' T1> → seq <'T2> → seq <' U> Crée une nouvelle collection dont les éléments sont les résultats de l'application de la fonction donnée aux paires d'éléments correspondantes des deux séquences. Si une séquence d'entrée est plus courte que l'autre, les éléments restants de la séquence plus longue sont ignorés.
mapi: (int → 'T →' U) → seq <'T> → seq <' U> Crée une nouvelle collection dont les éléments sont les résultats de l'application de la fonction donnée à chacun des éléments de la collection. L'index entier passé à la fonction indique l'index (à partir de 0) de l'élément en cours de transformation.
max: seq <'T> →' T Renvoie le plus grand de tous les éléments de la séquence, comparé à l'aide d'Operators.max.
maxBy: ('T →' U) → seq <'T> →' T Renvoie le plus grand de tous les éléments de la séquence, comparé à l'aide d'Operators.max sur le résultat de la fonction.
min: seq <'T> →' T Renvoie le plus bas de tous les éléments de la séquence, comparé à l'aide de Operators.min.
minBy: ('T →' U) → seq <'T> →' T Renvoie le plus petit de tous les éléments de la séquence, comparé à l'aide de Operators.min sur le résultat de la fonction.
nième: int → seq <'T> →' T Calcule le nième élément de la collection.
ofArray: 'T tableau → seq <' T> Affiche le tableau donné sous forme de séquence.
ofList: 'T liste → seq <' T> Affiche la liste donnée sous forme de séquence.
par paire: seq <'T> → seq <' T * 'T> Renvoie une séquence de chaque élément de la séquence d'entrée et de son prédécesseur, à l'exception du premier élément qui n'est renvoyé que comme prédécesseur du deuxième élément.
choisir: (option 'T →' U) → seq <'T> →' U Applique la fonction donnée aux éléments successifs, retournant la première valeur où la fonction renvoie un Some valeur.
lecture seule: seq <'T> → seq <' T> Crée un nouvel objet séquence qui délègue à l'objet séquence donné. Cela garantit que la séquence d'origine ne peut pas être redécouverte et mutée par une conversion de type. Par exemple, si un tableau est donné, la séquence retournée renverra les éléments du tableau, mais vous ne pouvez pas convertir l'objet séquence retourné en tableau.
réduire: ('T →' T → 'T) → seq <' T> → 'T Applique une fonction à chaque élément de la séquence, en enfilant un argument d'accumulateur dans le calcul. Commencez par appliquer la fonction aux deux premiers éléments. Introduisez ensuite ce résultat dans la fonction avec le troisième élément et ainsi de suite. Renvoie le résultat final.
scan: ('State →' T → 'State) →' State → seq <'T> → seq <' State> Comme Seq.fold, mais calcule à la demande et renvoie la séquence des résultats intermédiaires et finaux.
singleton: 'T → seq <' T> Renvoie une séquence qui ne produit qu'un seul élément.
sauter: int → seq <'T> → seq <' T> Renvoie une séquence qui ignore un nombre spécifié d'éléments de la séquence sous-jacente, puis renvoie les éléments restants de la séquence.
skipWhile: ('T → booléen) → seq <' T> → seq <'T> Renvoie une séquence qui, lorsqu'elle est itérée, ignore les éléments de la séquence sous-jacente tandis que le prédicat donné renvoie true, puis donne les éléments restants de la séquence.
trier: seq <'T> → seq <' T> Donne une séquence ordonnée par clés.
sortBy: (touche 'T →') → seq <'T> → seq <' T> Applique une fonction de génération de clé à chaque élément d'une séquence et produit une séquence ordonnée par clés. Les clés sont comparées à l'aide d'une comparaison générique implémentée par Operators.compare.
somme: seq <^ T> → ^ T Renvoie la somme des éléments de la séquence.
sommeBy Renvoie la somme des résultats générés en appliquant la fonction à chaque élément de la séquence.
prendre: int → seq <'T> → seq <' T> Renvoie les premiers éléments de la séquence jusqu'à un nombre spécifié.
takeWhile: ('T → booléen) → seq <' T> → seq <'T> Renvoie une séquence qui, lorsqu'elle est itérée, produit des éléments de la séquence sous-jacente tandis que le prédicat donné renvoie true, puis ne renvoie aucun autre élément.
toArray: seq <'T> →' T [] Crée un tableau à partir de la collection donnée.
toList: seq <'T> →' T liste Crée une liste à partir de la collection donnée.
tronquer: int → seq <'T> → seq <' T> Renvoie une séquence qui, lorsqu'elle est énumérée, ne renvoie pas plus d'un nombre spécifié d'éléments.
tryFind: ('T → bool) → seq <' T> → 'T option Renvoie le premier élément pour lequel la fonction donnée renvoie true, ou None si aucun élément de ce type n'existe.
tryFindIndex: ('T → bool) → seq <' T> → option int Renvoie l'index du premier élément de la séquence qui satisfait le prédicat donné, ou None si aucun élément de ce type n'existe.
tryPick: (option 'T →' U) → seq <'T> →' option U Applique la fonction donnée aux éléments successifs, retournant la première valeur où la fonction renvoie un Some valeur.
déplier: (option 'Etat →' T * 'Etat) →' Etat → seq <'T> Renvoie une séquence contenant les éléments générés par le calcul donné.
où: ('T → bool) → seq <' T> → seq <'T> Renvoie une nouvelle collection contenant uniquement les éléments de la collection pour lesquels le prédicat donné retourne true. Un synonyme de Seq.filter.
fenêtré: int → seq <'T> → seq <' T []> Renvoie une séquence qui produit des fenêtres glissantes contenant des éléments tirés de la séquence d'entrée. Chaque fenêtre est renvoyée sous la forme d'un nouveau tableau.
zip: seq <'T1> → seq <' T2> → seq <'T1 *' T2> Combine les deux séquences en une liste de paires. Il n'est pas nécessaire que les deux séquences aient des longueurs égales - lorsqu'une séquence est épuisée, tous les éléments restants de l'autre séquence sont ignorés.
zip3: seq <'T1> → seq <' T2> → seq <'T3> → seq <' T1 * 'T2 *' T3> Combine les trois séquences en une liste de triplets. Les séquences n'ont pas besoin d'avoir la même longueur - lorsqu'une séquence est épuisée, tous les éléments restants dans les autres séquences sont ignorés.

Les exemples suivants illustrent les utilisations de certaines des fonctionnalités ci-dessus -

Exemple 1

Ce programme crée une séquence vide et la remplit plus tard -

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

Lorsque vous compilez et exécutez le programme, il produit la sortie suivante -

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

Veuillez noter que -

  • La méthode Seq.empty crée une séquence vide.

  • La méthode Seq.singleton crée une séquence d'un seul élément spécifié.

  • La méthode Seq.init crée une séquence pour laquelle les éléments sont créés à l'aide d'une fonction donnée.

  • Les méthodes Seq.ofArray et Seq.ofList <'T> créent des séquences à partir de tableaux et de listes.

  • La méthode Seq.iter permet d'itérer dans une séquence.

Exemple 2

La méthode Seq.unfold génère une séquence à partir d'une fonction de calcul qui prend un état et le transforme pour produire chaque élément suivant de la séquence.

La fonction suivante produit les 20 premiers nombres naturels -

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

Lorsque vous compilez et exécutez le programme, il produit la sortie suivante -

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

Exemple 3

La méthode Seq.truncate crée une séquence à partir d'une autre séquence, mais limite la séquence à un nombre spécifié d'éléments.

La méthode Seq.take crée une nouvelle séquence qui contient un nombre spécifié d'éléments à partir du début d'une séquence.

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

Lorsque vous compilez et exécutez le programme, il produit la sortie suivante -

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