javascript - Usando map() en un iterador
map javascript (6)
La forma más simple y menos eficaz de hacer esto es:
Array.from(m).map(([key,value]) => /* whatever */)
Mejor todavía
Array.from(m, ([key, value]) => /* whatever */))
Array.from
toma cualquier cosa iterable o similar a una matriz y la convierte en una matriz!
Como Daniel señala en los comentarios, podemos agregar una función de mapeo a la conversión para eliminar una iteración y, posteriormente, una matriz intermedia.
El uso de
Array.from
moverá su rendimiento de
O(1)
a
O(n)
como @hraban señala en los comentarios.
Como
m
es un
Map
y no pueden ser infinitos, no tenemos que preocuparnos por una secuencia infinita.
Para la mayoría de los casos, esto será suficiente.
Hay un par de otras formas de recorrer un mapa.
Usando para
forEach
m.forEach((value,key) => /* stuff */ )
Usando para
for..of
var myMap = new Map();
myMap.set(0, ''zero'');
myMap.set(1, ''one'');
for (var [key, value] of myMap) {
console.log(key + '' = '' + value);
}
// 0 = zero
// 1 = one
Digamos que tenemos un mapa:
let m = new Map();
, utilizando
m.values()
devuelve un iterador de mapa.
Pero no puedo usar
forEach()
o
map()
en ese iterador e implementar un ciclo while en ese iterador parece un antipatrón ya que ES6 ofrece funciones como
map()
.
Entonces, ¿hay alguna manera de usar
map()
en un iterador?
La forma más simple y más
Array.from
es usar el segundo argumento de
Array.from
para lograr esto:
const map = new Map()
map.set(''a'', 1)
map.set(''b'', 2)
Array.from(map, ([key, value]) => `${key}:${value}`)
// [''a:1'', ''b:2'']
Este enfoque funciona para cualquier iteración
no infinita
.
Y evita tener que usar una llamada separada a
Array.from(map).map(...)
que iteraría por el iterable dos veces y sería peor para el rendimiento.
Podría definir otra función de iterador para recorrer esto:
function* generator() {
for(let i = 0; i < 10; i++) {
console.log(i);
yield i;
}
}
function* mapIterator(iterator, mapping) {
while (true) {
let result = iterator.next();
if (result.done) {
break;
}
yield mapping(result.value);
}
}
let values = generator();
let mapped = mapIterator(values, (i) => {
let result = i*2;
console.log(`x2 = ${result}`);
return result;
});
console.log(''The values will be generated right now.'');
console.log(Array.from(mapped).join('',''));
Ahora puede preguntarse: ¿por qué no usar
Array.from
en
Array.from
lugar?
Como esto se ejecutará en todo el iterador, guárdelo en una matriz (temporal), repítalo nuevamente y
luego
realice la asignación.
Si la lista es enorme (o incluso potencialmente infinita), esto conducirá a un uso innecesario de la memoria.
Por supuesto, si la lista de elementos es bastante pequeña, usar
Array.from
debería ser más que suficiente.
Podría usar itiriri que implementa métodos de tipo matriz para iterables:
import { query } from ''itiriri'';
let m = new Map();
// set map ...
query(m).filter([k, v] => k < 10).forEach([k, v] => console.log(v));
let arr = query(m.values()).map(v => v * 10).toArray();
Puede recuperar un iterador sobre el iterable, luego devolver otro iterador que llame a la función de devolución de llamada de mapeo en cada elemento iterado.
const map = (iterable, callback) => {
return {
[Symbol.iterator]() {
const iterator = iterable[Symbol.iterator]();
return {
next() {
const r = iterator.next();
if (r.done)
return r;
else {
return {
value: callback(r.value),
done: false,
};
}
}
}
}
}
};
// Arrays are iterable
console.log(...map([0, 1, 2, 3, 4], (num) => 2 * num)); // 0 2 4 6 8
Iterando sobre un mapa
1) Iterar sobre las teclas del mapa
Map ofrece el método de claves () que podemos usar para iterar en todas las claves.
for (const k of m.keys()) {
console.log(k)
}
2) iterar sobre los valores del mapa
El objeto Map ofrece el método de valores () que podemos usar para iterar en todos los valores:
for (const v of m.values()) {
console.log(v)
}
3) Iterar sobre la clave del mapa, pares de valores
El objeto Map ofrece el método de entradas () que podemos usar para iterar en todos los valores:
for (const [k, v] of m.entries()) {
console.log(k, v)
}
También podemos simplificar a
for (const [k, v] of m) {
console.log(k, v)
}