Hamburger Icon
Uso de Maps y Sets en JavaScript

Uso de Maps y Sets en JavaScript

Estamos tan acostumbrados a ir tirando con arrays y objetos, que a veces nos olvidamos de que tenemos otras estructuras disponibles que en algunos casos nos pueden ser de mucha utilidad. Vamos a ver en qué consisten los maps y los sets.

Usando Map en JavaScript

No confundir con Array.prototype.map(). No, estamos hablando de la estructura Map, que es una colección de elementos con clave y valor, como los objetos. La diferencia con éstos, es que en un mapa podemos almacenar cualquier tipo de dato en la clave.

En un objeto las claves siempre serán una cadena de texto o un símbolo JavaScript, pero en un mapa podemos usar cualquier tipo de dato en la clave. Mira:

const miMapa = new Map()

miMapa.set({ nombre: "Pol" }, "información")
console.log(miMapa) // {nombre: "Pol"}: "información"

Hemos guardado un objeto como clave.

Además, en un mapa el orden de los elementos a medida que vamos añadiendo se mantiene, a diferencia con los objetos. Ten en cuenta también que los mapas no se pueden reordenar.

Si conocemos la información que vamos a almacenar en la coleción y no hay ninguna clave que sea de otro tipo que texto o símbolo, entonces un objeto puede ser la solución. Ahora bien, si las claves de la colección no se conocen hasta la ejecución del código, entonces un mapa será la solución ideal para evitar posibles errores.

Otro caso de uso es cuando tenemos que almacenar una cantidad muy grande de información en la colección. Habitualmente un mapa rendirá mejor que un objeto. Tienen un mejor rendimiento en la adición y eliminación de elementos, así que si esa es una tarea muy habitual en la colección, además de ser bastante grande, usa mejor un mapa.

Si tu intención es serializar la colección a formato JSON, entonces usa objetos, ya que por defecto no hay ningún serializador nativo para mapas, aunque podrías llegar a hacer uno personalizado.

Cómo usar mapas

Así podemos crear un mapa, además de añadir, eliminar y actualizar elementos:

// creamos un nuevo mapa
const miCompra = new Map()

// añadimos elementos a la lista de la compra (elemento, precio)
miCompra.set("Café", 5)
miCompra.set("Queso", 2)
miCompra.set("Salmón", 7)

// actualizamos el precio del café
miCompra.set("Café", 6)

// eliminamos un elemento
miCompra.delete("Café")

// eliminamos todos los elementos
miCompra.clear()

Si queremos crear un elemento nuevo usamos set, pero si queremos recoger uno de los elementos podemos usar get:

const miCompra = new Map()

miCompra.set("Café", 5)
miCompra.set("Queso", 2)
miCompra.set("Salmón", 7)

// obtenemos el valor de un elemento
const item = miCompra.get("Queso")
console.log(item) // 2

Para iterar un mapa, tenemos los métodos keys(), values() y entries() que devuelven un iterador:

const miCompra = new Map()

miCompra.set("Café", 5)
miCompra.set("Queso", 2)
miCompra.set("Salmón", 7)

// iteramos las claves del mapa
for (const item of miCompra.keys()) {
  console.log(item)
} // Café, Queso, Salmón

// iteramos los valores del mapa
for (const precio of miCompra.values()) {
  console.log(precio)
} // 5, 2, 7

// iteramos cada elemento del mapa con su clave y valor
for (const elemento of miCompra.entries()) {
  console.log(elemento)
} // ["Café", 5], ["Queso", 2], ["Salmón", 7]

Y finalmente, también podemos comprobar el tamaño del mapa y saber si hay cierto elemento con size() y has() respectivamente:

const miCompra = new Map()

miCompra.set("Café", 5)
miCompra.set("Queso", 2)
miCompra.set("Salmón", 7)

// ¿tenemos salmón?
console.log(miCompra.has("Salmón")) // true

// ¿tenemos ternera?
console.log(miCompra.has("Ternera")) // false

// total elementos en la lista de la compra
console.log(miCompra.size) // 3

Como puedes ver, tenemos algunas cosas en los mapas que en los objetos no. Resumiendo, un mapa es una buena opción cuando:

  • Tenemos muchos elementos
  • Queremos preservar un orden
  • Necesitaremos contar la cantidad de elementos habitualmente
  • No conocemos el tipo de dato que habrá en las claves
  • Sabemos que vamos a guardar datos que no son ni texto ni símbolos en las claves

Usando Set en JavaScript

Un set es una colección de elementos sin claves, es decir, son parecidos a un array. La diferencia, es que en los sets no hay elementos repetidos. ¿Cuántas veces has alimentado un array de elementos para posteriormente eliminar sus repetidos? Sí, a todos nos ha pasado.

Cuando se añade un nuevo elemento a un set, automáticamente se revisa si ese elemento ya existe antes de proceder. Al igual que con los mapas, mantienen el orden de los elementos que se van añadiendo y no es posible reordenarlos.

Cómo usar sets

Así creamos, añadimos y eliminamos elementos:

// creamos un nuevo set
const miLista = new Set()

// añadimos tres valores
miLista.add(1)
miLista.add(2)
miLista.add(3)

// esto no añade ningún valor nuevo
miLista.add(1) // 1 ya existe

// eliminamos un elemento
miLista.delete(2)

Ojo no caigas en la trampa de los repetidos con los objetos. Mira:

const miLista = new Set()

const item1 = { instrumento: "guitarra" }
const item2 = { instrumento: "bajo" }
const item3 = { instrumento: "batería" }

miLista.add(item1)
miLista.add(item2)
miLista.add(item3)

// esto no añade ningún elemento nuevo
miLista.add(item3)
console.log(miLista.size) // 3

// en cambio, esto sí
miLista.add({ instrumento: "batería" })
console.log(miLista.size) // 4

Esto sucede porque en JavaScript, las variables guardan la referencia a los objetos, no su contenido. Cuando estamos añadiendo el cuarto elemento, realmente no se trata del mismo objeto, es otro diferente con la misma estructura.

Podemos iterar un set con el método values():

const miLista = new Set()

miLista.add(1)
miLista.add(2)
miLista.add(3)

for (const elemento of miLista.values()) {
  console.log(elemento)
} // 1, 2, 3

Además, con el método has() podemos comprobar si un elemento existe o no en el set:

const miLista = new Set()

miLista.add(1)
miLista.add(2)
miLista.add(3)

console.log(miLista.has(4)) // false
console.log(miLista.has(1)) // true

Podemos convertir un set a array y viceversa de forma sencilla:

const miLista = new Set()

miLista.add(1)
miLista.add(2)
miLista.add(3)

// convertimos el set en un array
const nuevaLista = [...miLista.values()]
console.log(Array.isArray(nuevaLista)) // true

// convertimos un array en un set
const conRepetidos = [1, 2, 3, 3]
const sinRepetidos = new Set(conRepetidos)
console.log(sinRepetidos) // [1, 2, 3]

Esto nos permitirá hacer cambios según nos interese, por ejemplo, para ordenar el set transformándolo primero en un array y luego volviendo a crear el set después de ordenarlo.

En resumen, el set te puede ser útil si:

  • Quieres evitar duplicados
  • No te importa el orden de los elementos
  • no vas a necesitar los métodos map(), filter() y reduce()

Como los sets no tienen disponibles los métodos map(), filter() y reduce(), quizás te sea más cómodo trabajar con arrays y hacer la transformación a sets en momentos concretos para eliminar duplicados.

Conclusiones

Los mapas y los sets tienen ciertos casos de uso que nos pueden ser muy útiles y facilitarnos el trabajo. Estas dos estructuras fueron introducidas con ES6 y desde entonces nos han ayudado a mejorar la interacción con los objetos y arrays clásicos, pudiendo superar algunas de sus limitaciones.