F # - Secuencias

Las secuencias, como las listas, también representan una colección ordenada de valores. Sin embargo, los elementos de una secuencia o expresión de secuencia se calculan cuando es necesario. No se calculan a la vez y, por esta razón, se utilizan para representar estructuras de datos infinitas.

Definición de secuencias

Las secuencias se definen utilizando la siguiente sintaxis:

seq { expr }

Por ejemplo,

let seq1 = seq { 1 .. 10 }

Creación de secuencias y expresiones de secuencias

De manera similar a las listas, puede crear secuencias usando rangos y comprensiones.

Las expresiones de secuencia son las expresiones que puede escribir para crear secuencias. Estos se pueden hacer:

  • Especificando el rango.
  • Especificando el rango con incremento o decremento.
  • Usando el yield palabra clave para producir valores que se conviertan en parte de la secuencia.
  • Utilizando el operador →.

Los siguientes ejemplos demuestran el concepto:

Ejemplo 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

Cuando compila y ejecuta el programa, produce el siguiente resultado:

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

Ejemplo 2

El siguiente programa imprime los números primos del 1 al 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

Cuando compila y ejecuta el programa, produce el siguiente resultado:

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

Operaciones básicas en secuencia

La siguiente tabla muestra las operaciones básicas sobre el tipo de datos de secuencia:

Valor Descripción
añadir: seq <'T> → seq <' T> → seq <'T> Envuelve las dos enumeraciones dadas como una sola enumeración concatenada.
promedio: seq <^ T> → ^ T Devuelve el promedio de los elementos de la secuencia.
averageBy: ('T → ^ U) → seq <' T> → ^ U Devuelve el promedio de los resultados generados al aplicar la función a cada elemento de la secuencia.
caché: seq <'T> → seq <' T> Devuelve una secuencia que corresponde a una versión en caché de la secuencia de entrada.
emitir: IEnumerable → seq <'T> Envuelve un sistema de tipo flexible. Secuencia de colecciones como secuencia escrita.
elija: ('T →' U opción) → seq <'T> → seq <' U> Aplica la función dada a cada elemento de la lista. Devuelve la lista compuesta por los resultados de cada elemento donde la función devuelveSome.
recopilar: ('T →' Colección) → seq <'T> → seq <' U> Aplica la función dada a cada elemento de la secuencia y concatena todos los resultados.
comparar con: ('T →' T → int) → seq <'T> → seq <' T> → int Compara dos secuencias usando la función de comparación dada, elemento por elemento.
concat: seq <'Colección> → seq <' T> Combina la enumeración de enumeraciones dada como una única enumeración concatenada.
countBy: ('T →' Tecla) → seq <'T> → seq <' Tecla * int> Aplica una función de generación de claves a cada elemento de una secuencia y devuelve una secuencia que produce claves únicas y su número de ocurrencias en la secuencia original.
retardo: (unidad → seq <'T>) → seq <' T> Devuelve una secuencia que se construye a partir de la especificación retrasada dada de una secuencia.
distinto: seq <'T> → seq <' T> Devuelve una secuencia que no contiene entradas duplicadas según el hash genérico y las comparaciones de igualdad de las entradas. Si un elemento aparece varias veces en la secuencia, las últimas ocurrencias se descartan.
distintivoBy: (Tecla 'T →') → seq <'T> → seq <' T> Devuelve una secuencia que no contiene entradas duplicadas según el hash genérico y las comparaciones de igualdad de las claves devueltas por la función generadora de claves dada. Si un elemento aparece varias veces en la secuencia, las últimas ocurrencias se descartan.
vacío: seq <'T> Crea una secuencia vacía.
exactamenteOne: seq <'T> →' T Devuelve el único elemento de la secuencia.
existe: ('T → bool) → seq <' T> → bool Comprueba si algún elemento de la secuencia satisface el predicado dado.
existe2: ('T1 →' T2 → bool) → seq <'T1> → seq <' T2> → bool Comprueba si algún par de elementos correspondientes de las secuencias de entrada satisface el predicado dado.
filtro: ('T → bool) → seq <' T> → seq <'T> Devuelve una nueva colección que contiene solo los elementos de la colección para la que devuelve el predicado dado true.
buscar: ('T → bool) → seq <' T> → 'T Devuelve el primer elemento para el que devuelve la función dada. true.
findIndex: ('T → bool) → seq <' T> → int Devuelve el índice del primer elemento para el que devuelve la función dada. true.
fold: ('Estado →' T → 'Estado) →' Estado → seq <'T> →' Estado Aplica una función a cada elemento de la colección, enhebrando un argumento acumulador a través del cálculo. Si la función de entrada es f y los elementos son i0 ... iN, entonces esta función calcula f (... (fs i0) ...) iN.
forall: ('T → bool) → seq <' T> → bool Comprueba si todos los elementos de la secuencia satisfacen el predicado dado.
forall2: ('T1 →' T2 → bool) → seq <'T1> → seq <' T2> → bool Comprueba que todos los pares de elementos extraídos de las dos secuencias satisfacen el predicado dado. Si una secuencia es más corta que la otra, los elementos restantes de la secuencia más larga se ignoran.
groupBy: ('T →' Tecla) → seq <'T> → seq <' Tecla * seq <'T >> Aplica una función de generación de claves a cada elemento de una secuencia y produce una secuencia de claves únicas. Cada clave única también contiene una secuencia de todos los elementos que coinciden con esta clave.
cabeza: seq <'T> →' T Devuelve el primer elemento de la secuencia.
init: int → (int → 'T) → seq <' T> Genera una nueva secuencia que, cuando se itera, devuelve elementos sucesivos llamando a la función dada, hasta el recuento dado. Los resultados de llamar a la función no se guardan, es decir, la función se vuelve a aplicar según sea necesario para regenerar los elementos. A la función se le pasa el índice del elemento que se está generando.
initInfinite: (int → 'T) → seq <' T> Genera una nueva secuencia que, cuando se itera, devolverá elementos sucesivos llamando a la función dada. Los resultados de llamar a la función no se guardan, es decir, la función se volverá a aplicar según sea necesario para regenerar los elementos. A la función se le pasa el índice del elemento que se está generando.
isEmpty: seq <'T> → bool Comprueba si una secuencia tiene elementos.
iter: ('T → unidad) → seq <' T> → unidad Aplica la función dada a cada elemento de la colección.
iter2: ('T1 →' T2 → unidad) → seq <'T1> → seq <' T2> → unidad Aplica la función dada a dos colecciones simultáneamente. Si una secuencia es más corta que la otra, los elementos restantes de la secuencia más larga se ignoran.
iteri: (int → 'T → unidad) → seq <' T> → unidad Aplica la función dada a cada elemento de la colección. El entero pasado a la función indica el índice del elemento.
último: seq <'T> →' T Devuelve el último elemento de la secuencia.
longitud: seq <'T> → int Devuelve la longitud de la secuencia.
mapa: ('T →' U) → seq <'T> → seq <' U> Crea una nueva colección cuyos elementos son el resultado de aplicar la función dada a cada uno de los elementos de la colección. La función dada se aplicará a medida que los elementos se demanden utilizando el método MoveNext en los enumeradores recuperados del objeto.
mapa2: ('T1 →' T2 → 'U) → seq <' T1> → seq <'T2> → seq <' U> Crea una nueva colección cuyos elementos son el resultado de aplicar la función dada a los pares de elementos correspondientes de las dos secuencias. Si una secuencia de entrada es más corta que la otra, los elementos restantes de la secuencia más larga se ignoran.
mapi: (int → 'T →' U) → seq <'T> → seq <' U> Crea una nueva colección cuyos elementos son el resultado de aplicar la función dada a cada uno de los elementos de la colección. El índice entero pasado a la función indica el índice (desde 0) del elemento que se está transformando.
máx: seq <'T> →' T Devuelve el mayor de todos los elementos de la secuencia, comparado mediante Operators.max.
maxBy: ('T →' U) → seq <'T> →' T Devuelve el mayor de todos los elementos de la secuencia, comparado utilizando Operators.max en el resultado de la función.
min: seq <'T> →' T Devuelve el más bajo de todos los elementos de la secuencia, comparado con Operators.min.
minBy: ('T →' U) → seq <'T> →' T Devuelve el más bajo de todos los elementos de la secuencia, comparado utilizando Operators.min en el resultado de la función.
nth: int → seq <'T> →' T Calcula el enésimo elemento de la colección.
ofArray: 'T matriz → seq <' T> Visualiza la matriz dada como una secuencia.
ofList: 'T lista → seq <' T> Visualiza la lista dada como una secuencia.
por pares: seq <'T> → seq <' T * 'T> Devuelve una secuencia de cada elemento en la secuencia de entrada y su predecesor, con la excepción del primer elemento que solo se devuelve como el predecesor del segundo elemento.
elegir: ('T →' opción U) → seq <'T> →' U Aplica la función dada a elementos sucesivos, devolviendo el primer valor donde la función devuelve un Some valor.
solo lectura: seq <'T> → seq <' T> Crea un nuevo objeto de secuencia que se delega en el objeto de secuencia dado. Esto asegura que la secuencia original no pueda ser redescubierta y mutada por un elenco de tipos. Por ejemplo, si se le da una matriz, la secuencia devuelta devolverá los elementos de la matriz, pero no puede convertir el objeto de secuencia devuelto en una matriz.
reducir: ('T →' T → 'T) → seq <' T> → 'T Aplica una función a cada elemento de la secuencia, enhebrando un argumento acumulador a través del cálculo. Comience aplicando la función a los dos primeros elementos. Luego, introduzca este resultado en la función junto con el tercer elemento y así sucesivamente. Devuelve el resultado final.
escanear: ('Estado →' T → 'Estado) →' Estado → seq <'T> → seq <' Estado> Como Seq.fold, pero calcula bajo demanda y devuelve la secuencia de resultados intermedios y finales.
singleton: 'T → seq <' T> Devuelve una secuencia que produce un solo elemento.
saltar: int → seq <'T> → seq <' T> Devuelve una secuencia que omite un número específico de elementos de la secuencia subyacente y luego produce los elementos restantes de la secuencia.
skipWhile: ('T → bool) → seq <' T> → seq <'T> Devuelve una secuencia que, cuando se itera, omite elementos de la secuencia subyacente mientras que el predicado dado devuelve true, y luego produce los elementos restantes de la secuencia.
ordenar: seq <'T> → seq <' T> Produce una secuencia ordenada por claves.
sortBy: (Tecla 'T →') → seq <'T> → seq <' T> Aplica una función de generación de claves a cada elemento de una secuencia y produce una secuencia ordenada por claves. Las claves se comparan mediante una comparación genérica implementada por Operators.compare.
suma: seq <^ T> → ^ T Devuelve la suma de los elementos de la secuencia.
sumBy Devuelve la suma de los resultados generados al aplicar la función a cada elemento de la secuencia.
tomar: int → seq <'T> → seq <' T> Devuelve los primeros elementos de la secuencia hasta un recuento especificado.
takeWhile: ('T → bool) → seq <' T> → seq <'T> Devuelve una secuencia que, cuando se itera, produce elementos de la secuencia subyacente mientras que el predicado dado devuelve true, y luego no devuelve más elementos.
toArray: seq <'T> →' T [] Crea una matriz a partir de la colección dada.
toList: seq <'T> →' T list Crea una lista de la colección dada.
truncar: int → seq <'T> → seq <' T> Devuelve una secuencia que, cuando se enumera, no devuelve más de un número específico de elementos.
tryFind: ('T → bool) → seq <' T> → 'T opción Devuelve el primer elemento para el que devuelve la función dada. true, o None si no existe tal elemento.
tryFindIndex: ('T → bool) → seq <' T> → opción int Devuelve el índice del primer elemento de la secuencia que satisface el predicado dado, o None si no existe tal elemento.
tryPick: ('T →' opción U) → seq <'T> →' opción U Aplica la función dada a elementos sucesivos, devolviendo el primer valor donde la función devuelve un Some valor.
desplegar: ('Estado →' T * 'opción de estado) →' Estado → seq <'T> Devuelve una secuencia que contiene los elementos generados por el cálculo dado.
donde: ('T → bool) → seq <' T> → seq <'T> Devuelve una nueva colección que contiene solo los elementos de la colección para la que devuelve el predicado dado true. Un sinónimo de filtro de secuencia.
en ventana: int → seq <'T> → seq <' T []> Devuelve una secuencia que produce ventanas deslizantes que contienen elementos extraídos de la secuencia de entrada. Cada ventana se devuelve como una nueva matriz.
zip: seq <'T1> → seq <' T2> → seq <'T1 *' T2> Combina las dos secuencias en una lista de pares. No es necesario que las dos secuencias tengan la misma longitud: cuando se agota una secuencia, se ignoran los elementos restantes de la otra secuencia.
zip3: seq <'T1> → seq <' T2> → seq <'T3> → seq <' T1 * 'T2 *' T3> Combina las tres secuencias en una lista de triples. No es necesario que las secuencias tengan la misma longitud: cuando se agota una secuencia, se ignoran los elementos restantes de las otras secuencias.

Los siguientes ejemplos demuestran los usos de algunas de las funcionalidades anteriores:

Ejemplo 1

Este programa crea una secuencia vacía y la llena más tarde -

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

Cuando compila y ejecuta el programa, produce el siguiente resultado:

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

Tenga en cuenta que -

  • El método Seq.empty crea una secuencia vacía.

  • El método Seq.singleton crea una secuencia de un solo elemento especificado.

  • El método Seq.init crea una secuencia para la que se crean los elementos utilizando una función determinada.

  • Los métodos Seq.ofArray y Seq.ofList <'T> crean secuencias a partir de matrices y listas.

  • El método Seq.iter permite iterar a través de una secuencia.

Ejemplo 2

El método Seq.unfold genera una secuencia a partir de una función de cálculo que toma un estado y lo transforma para producir cada elemento subsiguiente en la secuencia.

La siguiente función produce los primeros 20 números naturales:

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

Cuando compila y ejecuta el programa, produce el siguiente resultado:

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

Ejemplo 3

El método Seq.truncate crea una secuencia a partir de otra secuencia, pero limita la secuencia a un número específico de elementos.

El método Seq.take crea una nueva secuencia que contiene un número específico de elementos desde el inicio de una secuencia.

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

Cuando compila y ejecuta el programa, produce el siguiente resultado:

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