¿Cómo harías esto? Instintivamente, quiero hacer:
var myMap = new Map([["thing1", 1], ["thing2", 2], ["thing3", 3]]);
// wishful, ignorant thinking
var newMap = myMap.map((key, value) => value + 1); // Map { 'thing1' => 2, 'thing2' => 3, 'thing3' => 4 }
No he extraído mucho de la documentación sobre el nuevo protocolo de iteración .
Soy consciente de wu.js , pero estoy ejecutando un proyecto de Babel y no quiero incluir Traceur , de lo que parece que depende actualmente .
También no tengo ni idea de cómo extraer cómo lo hizo fitzgen / wu.js en mi propio proyecto.
Me encantaría una explicación clara y concisa de lo que me estoy perdiendo aquí. ¡Gracias!
Documentos para ES6 Map , FYI
javascript
ecmascript-6
neezer
fuente
fuente
Array.from
?map
función para usar en iterables, usandofor of
.Respuestas:
Por
.map
lo tanto , solo ofrece un valor que le importa ... Dicho esto, hay algunas formas de abordar esto:// instantiation const myMap = new Map([ [ "A", 1 ], [ "B", 2 ] ]); // what's built into Map for you myMap.forEach( (val, key) => console.log(key, val) ); // "A 1", "B 2" // what Array can do for you Array.from( myMap ).map(([key, value]) => ({ key, value })); // [{key:"A", value: 1}, ... ] // less awesome iteration let entries = myMap.entries( ); for (let entry of entries) { console.log(entry); }
Tenga en cuenta que estoy usando muchas cosas nuevas en ese segundo ejemplo ... ...
Array.from
toma cualquier iterable (en cualquier momento que use[].slice.call( )
, más Conjuntos y Mapas) y lo convierte en una matriz ... ... Mapas , cuando se convierte en una matriz, se convierte en una matriz de matrices, dondeel[0] === key && el[1] === value;
(básicamente, en el mismo formato con el que rellené previamente mi mapa de ejemplo, arriba).Estoy usando la desestructuración de la matriz en la posición del argumento de la lambda, para asignar esos puntos de matriz a los valores, antes de devolver un objeto para cada el.
Si está usando Babel, en producción, necesitará usar el polyfill del navegador de Babel (que incluye "core-js" y el "regenerador" de Facebook).
Estoy bastante seguro de que contiene
Array.from
.fuente
Array.from
para hacer esto. Su primer ejemplo no devuelve una matriz, por cierto..forEach
devuelveundefined
completamente, todo el tiempo, ya que el uso esperado deforEach
es una iteración simple basada en efectos secundarios (igual que ha sido desde ES5). Para usar esoforEach
, querrá construir una matriz y completarla manualmente, ya sea a través de dichoforEach
o mediante el iterador devuelto por.entries()
o.keys( )
o.values( )
.Array.from
no está haciendo nada increíblemente único, solo está ocultando esa fealdad particular de hacer dicho recorrido. Y sí, verifique que al incluirbabel-core/browser.js
(o lo que sea) obtiene.from
...Array.from
toma una función de mapa como parámetro, no necesita crear una matriz temporal solo para mapearla y descartarla.const obj = { x: 1 };
, cuando escribes un bloque de código, escribesif (...) { /* block */ }
, cuando escribes una función de flecha escribes() => { return 1; }
, entonces, ¿cómo sabe cuándo es un cuerpo de función, en comparación con las llaves de un objeto? Y la respuesta está entre paréntesis. De lo contrario, espera que el nombre sea una etiqueta para un bloque de código, una característica que se usa con poca frecuencia, pero puede etiquetarswitch
un bucle o un bucle, de modo que puedabreak;
salir de ellos por nombre. Entonces, si falta, tiene un cuerpo de función, con una etiqueta y la declaración1
, según el ejemplo de MDNSolo debe usar el operador Spread :
var myMap = new Map([["thing1", 1], ["thing2", 2], ["thing3", 3]]); var newArr = [...myMap].map(value => value[1] + 1); console.log(newArr); //[2, 3, 4] var newArr2 = [for(value of myMap) value = value[1] + 1]; console.log(newArr2); //[2, 3, 4]
fuente
Array.from
, para su información.[...myMap].map(mapFn)
creará una matriz temporal y luego la descartará.Array.from
toma amapFn
como segundo argumento, solo utilícelo.Array.from(myMap.values(), val => val + 1);
?Solo usa
Array.from(iterable, [mapFn])
.var myMap = new Map([["thing1", 1], ["thing2", 2], ["thing3", 3]]); var newArr = Array.from(myMap.values(), value => value + 1);
fuente
Array.from()
tomé una función de mapeo como un segundo parámetro opcional.Puede utilizar esta función:
function mapMap(map, fn) { return new Map(Array.from(map, ([key, value]) => [key, fn(value, key, map)])); }
uso:
var map1 = new Map([["A", 2], ["B", 3], ["C", 4]]); var map2 = mapMap(map1, v => v * v); console.log(map1, map2); /* Map { A → 2, B → 3, C → 4 } Map { A → 4, B → 9, C → 16 } */
fuente
Usando
Array.from
escribí una función de TypeScript que mapea los valores:function mapKeys<T, V, U>(m: Map<T, V>, fn: (this: void, v: V) => U): Map<T, U> { function transformPair([k, v]: [T, V]): [T, U] { return [k, fn(v)] } return new Map(Array.from(m.entries(), transformPair)); } const m = new Map([[1, 2], [3, 4]]); console.log(mapKeys(m, i => i + 1)); // Map { 1 => 3, 3 => 5 }
fuente
En realidad, todavía puede tener una
Map
con las claves originales después de convertir a una matriz conArray.from
. Eso es posible al devolver una matriz , donde el primer elemento es elkey
y el segundo es el transformadovalue
.const originalMap = new Map([ ["thing1", 1], ["thing2", 2], ["thing3", 3] ]); const arrayMap = Array.from(originalMap, ([key, value]) => { return [key, value + 1]; // return an array }); const alteredMap = new Map(arrayMap); console.log(originalMap); // Map { 'thing1' => 1, 'thing2' => 2, 'thing3' => 3 } console.log(alteredMap); // Map { 'thing1' => 2, 'thing2' => 3, 'thing3' => 4 }
Si no devuelve esa clave como primer elemento de la matriz, perderá las
Map
claves.fuente
Prefiero extender el mapa
export class UtilMap extends Map { constructor(...args) { super(args); } public map(supplier) { const mapped = new UtilMap(); this.forEach(((value, key) => mapped.set(key, supplier(value, key)) )); return mapped; }; }
fuente
Puede usar myMap.forEach y, en cada bucle, usar map.set para cambiar el valor.
myMap = new Map([ ["a", 1], ["b", 2], ["c", 3] ]); for (var [key, value] of myMap.entries()) { console.log(key + ' = ' + value); } myMap.forEach((value, key, map) => { map.set(key, value+1) }) for (var [key, value] of myMap.entries()) { console.log(key + ' = ' + value); }
fuente
const mapMap = (callback, map) => new Map(Array.from(map).map(callback)) var myMap = new Map([["thing1", 1], ["thing2", 2], ["thing3", 3]]); var newMap = mapMap((pair) => [pair[0], pair[1] + 1], myMap); // Map { 'thing1' => 2, 'thing2' => 3, 'thing3' => 4 }
fuente
Si no desea convertir el mapa completo en una matriz de antemano y / o desestructurar las matrices de valores clave, puede usar esta función tonta:
/** * Map over an ES6 Map. * * @param {Map} map * @param {Function} cb Callback. Receives two arguments: key, value. * @returns {Array} */ function mapMap(map, cb) { let out = new Array(map.size); let i = 0; map.forEach((val, key) => { out[i++] = cb(key, val); }); return out; } let map = new Map([ ["a", 1], ["b", 2], ["c", 3] ]); console.log( mapMap(map, (k, v) => `${k}-${v}`).join(', ') ); // a-1, b-2, c-3
fuente
Map.prototype.map = function(callback) { const output = new Map() this.forEach((element, key)=>{ output.set(key, callback(element, key)) }) return output } const myMap = new Map([["thing1", 1], ["thing2", 2], ["thing3", 3]]) // no longer wishful thinking const newMap = myMap.map((value, key) => value + 1) console.info(myMap, newMap)
Depende de su fervor religioso para evitar editar prototipos, pero encuentro que esto me permite mantenerlo intuitivo.
fuente
Puede map () matrices, pero no existe tal operación para Maps. La solución del Dr. Axel Rauschmayer :
Ejemplo:
let map0 = new Map([ [1, "a"], [2, "b"], [3, "c"] ]); const map1 = new Map( [...map0] .map(([k, v]) => [k * 2, '_' + v]) );
resultó en
{2 => '_a', 4 => '_b', 6 => '_c'}
fuente
Quizás de esta manera:
const m = new Map([["a", 1], ["b", 2], ["c", 3]]); m.map((k, v) => [k, v * 2]); // Map { 'a' => 2, 'b' => 4, 'c' => 6 }
Solo necesitaría parchear mono
Map
antes:Map.prototype.map = function(func){ return new Map(Array.from(this, ([k, v]) => func(k, v))); }
Podríamos haber escrito una forma más simple de este parche:
Map.prototype.map = function(func){ return new Map(Array.from(this, func)); }
Pero nos hubiéramos obligado a luego escribir
m.map(([k, v]) => [k, v * 2]);
que me parece un poco más doloroso y feo.Solo valores de mapeo
También podríamos mapear solo valores, pero no recomendaría esa solución ya que es demasiado específica. No obstante se puede hacer y tendríamos la siguiente API:
const m = new Map([["a", 1], ["b", 2], ["c", 3]]); m.map(v => v * 2); // Map { 'a' => 2, 'b' => 4, 'c' => 6 }
Al igual que antes de parchear de esta manera:
Map.prototype.map = function(func){ return new Map(Array.from(this, ([k, v]) => [k, func(v)])); }
Tal vez pueda tener ambos, nombrando el segundo
mapValues
para dejar en claro que en realidad no está mapeando el objeto como probablemente se esperaría.fuente