map y set

abril de 2022 (hace 2 años)visitas

Como se ha comentado en posts anteriores, las estructuras de datos y la manera de almacenarlas en la memoria es algo fundamental en el desarrollo de software. Realmente, mucha gente no tiene en cuenta a la hora de desarrollar la importancia de estas, por lo que luego suelen surgir diferentes problemas cuando la aplicación crece o cuando ocurre algo inesperado.

Bad programmers worry about the code. Good programmers worry about data structures and their relationships.

Con la llegada de ES6, se introdujeron dos nuevos "objetos" para almacenar datos y que fuera más sencillo acceder a estos, resolviendo problemas como el duplicado, orden, rendimiento, etc. Estos son Map y Set.

Map

Este objeto permite almacenar datos usando parejas de clave-valor, como vemos tiene cierta similitud con Object, pero tiene ciertas características que hacen que sea una opción muy recomendable frente a este:

  • Orden: El orden en el que se introducen los datos se preserva, en los objetos puede cambiar.
const city = new Map()

city.set('name', 'Granada') // 1
city.set('country', 'Spain') // 2
city.set('population', 232208) // 3

/*  
Map(3) {
    'name' => 'Granada',
    'country' => 'Spain',
    'population' => 232208,
}

El orden no cambia
*/


const city = new Object()

city.name = 'Granada' // ???
city.country = 'Spain' // ???
city.population = 232208 // ???

/* 
{
    country: 'Spain',
    name: 'Granada',
    population: 232208
}

El orden puede variar
*/
  • Accesibilidad: Tiene métodos específicos para acceder a los datos, como get, has, etc.
const city = new Map()

city.set('name', 'Granada')
city.set('country', 'Spain') 
city.set('population', 232208) 

city.get('name') // 'Granada'
city.has('population') // true
city.name // ❌
  • Rendimiento: Es muchísimo más rapido acceder y modificar los datos comparado con Object.
const cityMap = new Map()
const cityObject = new Object()
const cities = [...] // 385 cities (https://gist.github.com/norcal82/42440bd06a67eb7d9616)

for (let i = 0; i < cities.length; i++) {
        cityObject[i] = cities[i]
        cityMap.set(i, cities[i])
}

console.time('Object')
cityObject.hasOwnProperty(350)
console.timeEnd('Object')
// Object: 0.076ms

console.time('Map')
cityMap.has(350)
console.timeEnd('Map')
// Map: 0.012ms

console.time('Object')
cityObject[386] = 'Madrid'
console.timeEnd('Object')
// Object: 0.009ms

console.time('Map')
cityMap.set(386, 'Madrid')
console.timeEnd('Map')
// Map: 0.005ms
¿Cómo recorrer un Map?

Para poder recorrer un objeto Map, podemos usar for..of, este nos devolverá la clave y el valor.

for (let [key, value] of cityMap) {
    console.log(key, value)
}

Set

Este objeto permite almacenar datos únicos, es decir, que no se pueden repetir. En sus inicios, se dijo que sería el nuevo Array pero lamentablemente, no tiene muchos de los métodos nativos. Como pasa con Array, Set también conserva el orden de inserción.

El rendimiento comparado con Array es increíblemente más rápido:

const citySet = new Set()
const cityArray = []
const cities = [...] // Array 385 cities (https://gist.github.com/norcal82/42440bd06a67eb7d9616)

for (let i = 0; i < cities.length; i++) {
    cityArray.push(cities[i])
    citySet.add(cities[i])
}

console.time('Array')
cityArray.includes('Madrid')
console.timeEnd('Array')
// Array: 0.076ms

console.time('Set')
citySet.has('Madrid')
console.timeEnd('Set')
// Set: 0.01ms

console.time('Array')
cityArray[386] = 'Madrid'
console.timeEnd('Array')
// Array: 0.012ms

console.time('Set')
citySet.add('Madrid')
console.timeEnd('Set')
// Set: 0.005ms
¿Cómo recorrer un Set?

Para poder recorrer un objeto Set, podemos usar for..of, este nos devolverá el valor.

for (let city of citySet) {
    console.log(city)
}