Existen una serie de métodos que podemos utilizar sobre los iteradores que explicamos en el tema anterior. Estos métodos son unas funciones de ayuda para iteradores que nos permiten trabajar con conjuntos de datos de una forma cómoda, funcional y muy práctica.
Ayudante de iteradores
En primer lugar, vamos a analizar estos tres métodos completamente nuevos, que aparecen recientemente y podemos utilizar con los iteradores que tengamos en nuestro código:
Ayudante de iterador | Descripción |
---|---|
.take(limit) | Devuelve un iterador con los elementos desde 0 hasta el límite indicado. |
.drop(limit) | Devuelve un iterador con los elementos a partir del límite indicado. |
.toArray() | Devuelve un array con los valores del iterador hasta el final. |
Veamos algunos ejemplos para entender como funcionan estos interesantes métodos. Observa que partimos de un
const data = ["One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten"];
const iterator = data
.values()
.drop(3)
.take(2); // Array iterator {}
Mediante el método .values()
que vimos en el tema anterior, obtenemos un iterador del
- 1️⃣
drop(3)
Descarta los 3 primeros elementos - 2️⃣
take(2)
Toma los 2 siguientes elementos y descarta el resto
Entonces, nos devuelve un iterador que se guardará en la constante iterator
. Ahora, como todo iterador, podemos ejecutar el método .next()
para ir obteniendo los valores, que como debería ser, son los valores "Four"
y "Five"
:
// Manual
iterator.next(); // { value: "Four", done: false }
iterator.next(); // { value: "Five", done: false }
iterator.next(); // { value: undefined, done: true }
// Automática
[...iterator] // ["Four", "Five"]
También podemos utilizar el método .toArray()
para convertirlo en un 5
primeros elementos y nos quedamos con el resto hasta el final, conviertiéndolo en un
data
.values()
.drop(5)
.toArray(); // ['Six', 'Seven', 'Eight', 'Nine', 'Ten']
O En este siguiente ejemplo, donde:
- 1️⃣ Descartamos los
3
primeros elementos - 2️⃣ Tomamos los
4
siguientes elementos y descartamos el resto - 3️⃣ Lo convertimos a un array
data
.values()
.drop(3)
.take(4)
.toArray(); // ['Four', 'Five', 'Six', 'Seven']
Como puedes ver, una forma funcional de trabajar, bastante cómoda y práctica.
Usando generadores
Otra combinación de funcionalidades de Javascript que puede resultar interesante es combinar las funciones generadoras con los iteradores.
Observa el siguiente ejemplo, donde creamos una función generadora que genera números enteros indefinidamente. Esta función tiene un bucle infinito, sin embargo, es una función generadora y tiene un yield
que suspende la función hasta que se reanude, que incrementará el número y volverá a suspenderse:
function* generator() {
let i = 0;
while (true) {
yield i;
i += 1;
}
}
Esta función generadora simplemente nos va devolviendo en cada iteración un número entero, empezando en el 0
e incrementándolo en uno cada vez que se reanuda. Podemos utilizar dicha función como una generadora de arrays numéricos que gestionaremos mediante métodos para quedarnos con nuestro
Por ejemplo:
- 1️⃣ Ejecutamos la función generadora. Como tiene función
.next()
, se puede usar como iterador. - 2️⃣ Con
drop(25)
descartamos los25
primeros elementos. - 3️⃣ Con
take(5)
nos quedamos con los5
siguientes y descartamos el resto. - 4️⃣ Convertimos a
con toArray()
.
generator()
.drop(25)
.take(5)
.toArray(); // [25, 26, 27, 28, 29]
Otro ejemplo:
- 1️⃣ Generamos números con la función generadora.
- 2️⃣ Descartamos el primer número, es decir, el
0
. - 3️⃣ Tomamos los
100
siguientes, es decir, del1
al100
. - 4️⃣ Filtramos los que son múltiplos de
10
:10
,20
,30
, etc... - 5️⃣ Convertimos a
.
generator()
.drop(1)
.take(100)
.filter(n => n % 10 === 0)
.toArray(); // [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
Equivalencia con Array functions
Como habrás visto en el último ejemplo anterior, hemos utilizado .filter()
, ya que los iteradores también tienen algunos de los métodos de Array o Array functions, disponibles para utilizarlos en los iteradores:
Ayudante de iterador | Descripción | Equivalencia |
---|---|---|
Iterator.from(obj) | Crea un iterador a partir de una serie de elementos. | Array.from() |
❌ .forEach(f) | Realiza acciones sobre los elementos. | .forEach() |
.every(f) | Comprueba si todos los elementos cumplen una condición. | .every() |
.some(f) | Comprueba si alguno de los elementos cumplen una condición. | .some() |
.filter(f) | Filtra los elementos que cumplen una condición. | .filter() |
.map(f) | Transforma los elementos a otro elemento derivado. | .map() |
.flatMap(f) | Transforma y aplana la estructura del elemento. | .flatMap() |
.find(f) | Busca un elemento que cumpla una condición. | .find() |
.reduce(reducer, initial) | Aplica una función a los elementos, acumulándolo a un elemento. | .reduce() |
Tanto métodos como .forEach()
, .map()
, .filter()
, .flatMap()
y otros, como un equivalente al Array.from()
que nos permite crear iteradores para estructuras de datos concretas.
Veamos nuevamente en un ejemplo:
- 1️⃣ Creamos un array
messages
concon frases. - 2️⃣ Con
Iterator.from()
creamos un iterador que recorrerá dicha estructura (cada frase). - 3️⃣ El método
.flatMap()
permite hacer un.map()
que aplana los elementos de un. - 4️⃣ Una función
.map(text => text.split(" "))
separaría losen por espacios - 5️⃣ Pero como usamos
.flatMap()
, además aplanamos los - 6️⃣ Finalmente, con
.values()
nos quedamos con el iterador - 7️⃣ Reestructuramos con
[...data]
y obtenemos uncon cada palabra
const messages = ["Hola a todos", "Estoy muy contento", "Adiós"];
const it = Iterator.from(messages);
const data = it.flatMap(text => text.split(" ").values());
[...data] // ['Hola', 'a', 'todos', 'Estoy', 'muy', 'contento', 'Adiós']
Como habrás visto, una colección de utilidades muy interesantes y potentes para manipular y trabajar con datos mediante iteradores.