paint-brush
Cómo mapear un mapapor@maxired
71,935 lecturas
71,935 lecturas

Cómo mapear un mapa

por Maxence2016/12/19
Read on Terminal Reader
Read this story w/o Javascript

Demasiado Largo; Para Leer

2016 llega a su fin y ES6 está en todas partes. Pero con ES6, llegaron nuevas sintaxis y API. Este artículo tiene como objetivo responder a una pregunta muy específica: ¿Cómo mapear un mapa en una matriz?

Companies Mentioned

Mention Thumbnail
Mention Thumbnail
featured image - Cómo mapear un mapa
Maxence HackerNoon profile picture

2016 llega a su fin y ES6 está en todas partes. Pero con ES6, llegaron nuevas sintaxis y API. Este artículo tiene como objetivo responder a una pregunta muy específica: ¿Cómo mapear un mapa en una matriz?

tl; dr : solo use Array.from (mapa, ([clave, valor]) => valor)

Si está leyendo esto, significa que está interesado en una respuesta más completa. Para ser claros, estamos hablando aquí sobre el tipo de mapa de JavaScript. Las instancias de Map no proporcionan métodos de mapa. Este artículo trata sobre las formas de implementar uno.

Aún interesado ? Si es así, primero discutiremos sobre la necesidad de hacerlo, y principalmente por qué preferiría usar un Mapa en lugar de un Objeto normal.

Luego, discutiremos sobre las diferentes formas de hacer este mapeo.

Mapa vs Objeto

Antes de continuar, intentemos responder una pregunta simple: ¿Por qué alguien usaría Map en JavaScript?

Viniendo de otro idioma, como Java, usar Map parece bastante obvio. Pero, ¿y si vienes de un mundo anterior a ES6? ¿Alguna razón para usar Map over Object?

Para ser claros, no estoy abogando por usar Map en todas partes. Como siempre, es elección del desarrollador decidir qué se adapta mejor a la situación actual. Para ayudarlo a decidir, enumeraré aquí algunos puntos para los que podría preferir usar Mapa en lugar de un Objeto simple.

teclas escritas

Versión corta: puede usar cualquier tipo como clave para el mapa. No debe usar Object o Array, ni ninguna propiedad de tipo complejo de Otro objeto. Probablemente sea una mejor idea usar solo cuerdas.

Un objeto JavaScript regular, simplemente creado con {} , es muy flexible. Para cada clave, puede asignarle cualquiera de los otros tipos de JavaScript:






const obj = {};obj.first = 'myvalue';obj.arr = [];obj.number = 2;obj.deep = {};obj.map = new Map();

Además, a pesar de lo que puede leer en algunos lugares, puede agregar algunas claves dinámicas a su objeto:



const mykey = 'foo' + Math.random();const obj = {};obj[mykey] = 'bar';

O incluso, usando la nueva sintaxis de propiedades calculadas de ES6:

const mykey = 'foo' + Math.random();



const obj = {[miclave]: 'barra'}

Los últimos tres ejemplos deberían demostrarle que los objetos JS regulares son muy flexibles. Todavía hay una gran diferencia:

Mientras que el mapa puede tener claves de cualquier tipo, las claves de un objeto de JavaScript se convertirán como cadenas

Esta diferencia puede ser subtítulo, pero puede generar errores interesantes cuando no se entiende correctamente.




const mapa = nuevo Mapa();mapa.set(2, 'dos');mapa.set('2', 'DOS');// Mapa {2 => "dos", "2" => "DOS "}





const obj = {};obj[2] = 'dos';obj['2'] = 'DOS';obj;// Objeto {2: "DOS"}

En ese caso, ambos comportamientos pueden ser útiles según el contexto, pero ahora, tratemos de adivinar qué sucedería si intenta asignar un objeto:



const obj = {}const clave1 = { id: 'foo' }const clave2 = { id: 'bar' }


obj[clave1] = 'CLAVE1';obj[clave2] = 'CLAVE2';


obj[clave1];// CLAVE2"

En el ejemplo anterior, asignas a un objeto dos valores diferentes a los atributos proporcionados por un objeto, pero cuando intentas acceder al valor del primer atributo, obtienes el valor del segundo. Esto puede parecer extraño, pero debería ser lógico si lees detenidamente hasta ahora. Como se dijo antes, las propiedades del objeto se convierten en String antes de comenzar a usarse. Uno podría imaginar que la conversión se hace usando `JSON.stringify` o algo similar, pero la verdad es mucho más simple: simplemente hacemos `new String(prop).toString()`


String(key1).toString()// "[objeto Objeto]"


String(key2).toString()// "[objeto Objeto]"

nueva cadena (clave1).toString() === nueva cadena (clave2).toString()

Dado el ejemplo anterior, ahora es fácil entender por qué no es una buena idea usar tipos complejos, como Object, Arrays o Map como nombre de propiedad. Como se dijo, podría usar una capa de serialización antes de acceder a su propiedad, pero esto le daría un comportamiento diferente del mapa, si su objeto clave se modifica entre la asignación y el acceso.

Métodos integrados y atributo

Hemos visto anteriormente que si necesita usar claves complejas como nombres de propiedades, es mejor que use Map. Pero hay más razones para ello. Uno de ellos si la disponibilidad de métodos integrados.

El atributo incorporado más útil del objeto Map es probablemente el size . Probablemente no necesite más explicaciones y simplemente devuelva el número actual de elementos que hay en el mapa. Probablemente sea bastante obvio por qué alguien preferiría hacer map.size en lugar de Object.keys(obj).length .

Otros métodos de instancia, como map.keys() , map.values() y map.entries() , también son muy similares a lo que podríamos obtener con los métodos de objetos estáticos correspondientes, pero tienen una gran diferencia: devuelven iteradores y no matrices. No entraré en detalles aquí, pero volveré a ello en la segunda parte de este artículo.

Finalmente, se proporciona otro método como función de ayuda, que es map.has(key) y corresponde al método obj.hasOwnProperty(key) .

Algunos métodos más están disponibles para Map . Los detalles de la mayoría de ellos se proporcionarán en la siguiente sección.

Usarlo tiene referencias compartidas.

Además de la función Objeto complejo como clave, una de las razones para usar un mapa sería usarlo como referencias compartidas entre objetos, en un estilo POO puro.

Este mapa puede ser un Singleton, o simplemente compartirse entre instancias, pero pueden modificarlo. Esto está aquí en total oposición con las tendencias de todo inmutable del mundo de JavaScript, pero nuevamente, todo es una cuestión de contexto.

Viniendo para el mundo POO, map.get y map.set se sentirán muy naturales. Además, al más puro estilo CRUD, probablemente quieras poder eliminar un elemento del mapa. Aquí solo puede usar el método map.delete , que debe admitir que se siente mucho menos complicado que delete obj.key

Finalmente, también tiene el método map.clear , que le permite restablecer su Mapa al estado vacío.

Iteración

Una de las funciones más populares del objeto Map son las funciones de iteración. De hecho, Map viene con su nuevo amigo, la nueva forma for...of sintaxis.

La sintaxis for...of le permite escribir código como:

 let iterable = new Map([["a", 1], ["b", 2], ["c", 3]]);for (let entry of iterable) { console.log(entry);}// [a, 1]// [b, 2]// [c, 3]for (let [key, value] of iterable) { console.log(value);}// 1// 2// 3

Extraído de https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of#Iterating_over_a_Map

Personalmente, no soy un gran admirador de esas iteraciones de estilo C y prefiero usar funciones de orden superior. Parece que no soy el único, ya que esto también forma parte de la famosa guía de estilo de Airbnb .

Diferentes formas de mapear un mapa

No, obtuvimos lo básico de Map, ahora intentaremos resolver la pregunta inicial.

para… de

Si le gustó el for...of sintaxis, probablemente no esté interesado en el enfoque funcional ni en el inmutable. Si es así, es posible que desee utilizar la siguiente sintaxis para mapear un mapa.

 const iterable = new Map([["a", 1], ["b", 2], ["c", 3]]);

const valorescuadrados = [];

 for (let [key, value] of iterable) {

Me entristecería mucho que lo hiciera, ya que el objetivo de todo este artículo es evitar el uso de esta sintaxis.

No lo hemos descrito antes, pero esta sintaxis es posible porque Map es un objeto iterable, como el retorno de map.keys() y map.values() .

para cada

Además de los métodos de instancia de Map ya descritos, hay otro que no se ha discutido hasta ahora: map.forEach

El método forEach proporcionado aquí es muy similar al método forEach proporcionado por las matrices. Usando la misma sintaxis que usaría para Array, es bastante fácil implementar un método de mapa.

const mapMap = function (mapa, mapFunction){




const toReturn = [];map.forEach( function (value, key){ // tenga cuidado con los argumentos ordertoReturn.push(mapFunction(value, key));})


volver aRegresar;}

Usar esta sintaxis me parece bien, pero aún muestra un bucle y la mutación de la matriz toReturn . Esto estaría bien en archivos utils, pero probablemente no queramos contaminar nuestro código con esto en todas partes. La sintaxis a la que aspiraría sería puramente funcional nativa.

Array.from

Recientemente discutimos el hecho de que el método de map al que apuntamos está disponible en Array. Tal vez una buena solución sería implementar nuestro Map to an Array para llamar al método map. Además, también describimos que el Mapa es un Iterable.

Además, desde la especificación ES6, ahora hay nuevos métodos estáticos disponibles en Array. Uno de ellos es el método Array.from . Permite duplicar una matriz, convertir un objeto similar a una matriz en una matriz y también convertir un iterable en una matriz.

Ahora se puede escribir algo como:

Array.from(p).map(([clave, valor]) => valor * valor)

Creo que esto empieza a sentirse bastante bien. Estamos convirtiendo nuestro mapa en una matriz y luego aplicando un mapa en la parte superior. ¿Qué más podríamos desear? ¿Esto es en una sola operación? Buenas noticias, esto es posible.

De hecho, el método Array.from se puede llamar con un segundo argumento opcional, correspondiente a un método de mapeo.

Entonces podemos hacer:

Array.from(p, ([clave, valor]) => valor * valor)

Para mí, esta es la mejor manera de responder a la pregunta inicial: 'Cómo mapear un mapa en'

Conclusión

Hay ocasiones en las que usar un mapa en lugar de un objeto realmente tiene sentido. Cuando sea el caso, a veces todavía existe la necesidad de aplicar un método de mapa para transformar un Mapa en una matriz de objetos transformados. Al hacerlo, el mejor método para mí es usar el método Array.from con dos parámetros, uno para el mapa y el segundo para una función de mapeo.

Hacker Noon es como los hackers empiezan sus tardes. Somos parte de la familia @AMI . Ahora estamos aceptando presentaciones y estamos felices de discutir oportunidades de publicidad y patrocinio .

Para obtener más información, lea nuestra página de información , envíenos un mensaje/me gusta en Facebook o simplemente envíe un tweet/DM a @HackerNoon.

Si disfrutó de esta historia, le recomendamos que lea nuestras historias sobre tecnología más recientes y las historias sobre tecnología de moda. Hasta la próxima, ¡no des por sentadas las realidades del mundo!