Los Set en Javascript son estructuras de datos nativas muy interesantes para representar conjuntos de datos. La característica principal es que los datos insertados no se pueden repetir.
const set = new Set(); // Set({}) (Conjunto vacío)
const set = new Set([5, 6, 7, 8, 9]); // Set({5, 6, 7, 8, 9}) (Conjunto con 5 elementos)
const set = new Set([5, 5, 7, 8, 9]); // Set({5, 7, 8, 9}) (Conjunto con 4 elementos)
set.constructor.name; // "Set"
En los sets se puede incluir cualquier tipo de elemento, sin embargo, existe otra estructura derivada de los Set
que veremos más adelante que tiene ciertas diferencias y restricciones.
¿Qué son los Set?
Como hemos dicho, la característica principal de los conjuntos es que es una estructura que no permite valores repetidos, por lo que si intentamos insertar un valor que ya existe, no se insertará de nuevo y, por lo tanto, puedes tener la seguridad que un Set
nunca tendrá el mismo elemento almacenado, despreocupándote por ejemplo, si tienes que asegurarte de que no existan elementos duplicados, ya que es un caso que no puede ocurrir.
Propiedad o Método | Descripción |
---|---|
.size | Propiedad que devuelve el número de elementos que tiene el conjunto. |
.add(element) | Añade un elemento al conjunto (si no está repetido) y devuelve el set. Muta |
.has(element) | Comprueba si element ya existe en el conjunto. Devuelve si existe. |
.delete(element) | Elimina el element del conjunto. Devuelve si lo eliminó correctamente. |
.clear() | Vacía el conjunto completo. |
Vamos a analizar los diferentes métodos y propiedades que poseen los conjuntos.
Propiedad size
Si quieres saber cuántos elementos tienes en el conjunto, puedes utilizar la propiedad .size
, que funciona de forma muy similar al .length
de los array, por ejemplo.
const set = new Set();
set.size; // 0
const set = new Set([5, 6, 7, 8]);
set.size; // 4
const set = new Set([5, 6, 7, 8, 8]);
set.size; // 4 (El 8 sólo se inserta una vez)
Métodos
Veamos ahora los diferentes métodos que tienen las estructuras de conjuntos Set
.
Añadir elementos
En primer lugar, el método .add()
permite añadir un elemento al conjunto. Recuerda que aunque hasta ahora hemos utilizado sólo números, en el conjunto pueden insertarse otros tipos de elementos.
const set = new Set();
set.add(5);
set.add("A");
set.add(5); // No se inserta
set; // Set({5, "A"})
Observa que si intentamos añadir un elemento ya existente, no nos dará error, pero simplemente no se volverá a insertar. El método .add()
devuelve el set con la inserción realizada, es decir, devuelve una referencia al conjunto.
Comprobar si existen
Para comprobar si un elemento existe en un conjunto, podemos utilizar el método .has()
. Este método devuelve un true
. De lo contrario, false
.
const set = new Set([1, 2, 3]);
set.has(2); // true
set.has(34); // false
set.add(34);
set.has(34); // true
Borrar elementos
Si necesitamos borrar algún elemento del conjunto, podemos utilizar el método .delete()
. Al igual que el anterior, devuelve un true
, si no pudo realizarse (no existe el elemento), devolverá false
.
const set = new Set([1, 2, 3]);
set.delete(3); // true
set.delete(39); // false
set; // Set({1, 2})
Vacíar conjunto
Si por otro lado, queremos hacer un borrado completo de los elementos, utilizaremos el método .clear()
, que no devuelve nada. Simplemente borrará todos los elementos del conjunto y lo dejará vacío.
const set = new Set([1, 2, 3]);
set.clear();
set.size; // 0
Convertir a Arrays
Una de las cosas más interesantes y útiles de los Set
, es que al ser una estructura iterable (se puede recorrer), es muy sencillo utilizar desestructuración y convertirlo a un array (o viceversa):
const set = new Set([5, "A", [99, 10, 24]]);
set.size; // 3 (Contiene 3 elementos)
set.constructor.name; // "Set"
const array = [...set];
array.constructor.name; // "Array"
array; // [5, "A", [99, 10, 24]]
Cuidado cuando tengas conjuntos con tipos de datos más complejos con elementos anidados (arrays, objetos, etc...). Recuerda que son referencias y modificar un elemento referenciado, modificará el original.
Para evitar esto de forma sencilla, puedes utilizar la función structuredClone()
:
const set = new Set([5, "A", [99, 10, 24]]);
set.size; // 3
const clonedArray = [...structuredClone(set)];
const array = [...set];
clonedArray[2][0] = "Modified";
[...set][2][0]; // 99 (El original se mantiene intacto)
array[2][0] = "Modified";
[...set][2][0]; // "Modified" (El original ha mutado)
Además, también puedes hacer la operación inversa, para convertir un array en un Set
:
const array = [5, 4, 3, 3, 4];
const set = new Set(array);
set; // Set({ 5, 4, 3 })
¿Qué son los WeakSet?
A grandes rasgos, los WeakSet
son otro tipo de estructura de conjuntos, muy similar a Set
(también impide introducir elementos duplicados), sin embargo, tiene algunos matices y diferencias. Veamos esas diferencias.
Diferencias con los Set
Los Set
son una estructura de datos poco restrictiva, ya que puedes insertar cualquier tipo de elemento. Los WeakSet
no permiten insertar datos primitivos:
// *** Set
const set = new Set([1, "A", true]); // OK
const set = new Set([{ name: "Manz" }, [2, 30]]); // OK
// *** WeakSet
const set = new WeakSet([1, "A", true]);
// ERROR: Uncaught TypeError: Invalid value used in weak set
const set = new WeakSet([{ name: "Manz" }, [2, 30]]); // OK
Por otro lado, los WeakSet
utilizan referencias débiles a un objeto, es decir, si ese objeto no se utiliza (no está referenciado) en ninguna otra parte del código, se eliminará del WeakSet
en cuanto el Garbage Collector (Recolector de basura) lo decida para liberar memoria:
let element = { name: "Manz" };
const set = new WeakSet([element]);
set; // WeakSet({ { name: "Manz" } })
element = null;
set; // WeakSet({})
Observa que la penúltima línea, reasignamos a null
la variable element
. En ese caso, la zona de memoria donde está guardada la información { name: "Manz" }
no está referenciada en ninguna otra variable, por lo que Javascript considera que ya no es útil, y la borra del WeakSet
y de memoria.
OJO, es muy posible que al ejecutar este código y reasignar a
null
, la información aún permanezca en elset
. Esto ocurre porque la recolección de basura es un proceso que no ocurre instantáneamente, sino que se dispara cuando el navegador lo considera oportuno y necesita o necesitará memoria adicional.
Tabla de resumen de diferencias
A continuación, una tabla resumen de las diferencias entre Set
y WeakSet
:
Característica | Set | WeakSet |
---|---|---|
Se pueden insertar elementos repetidos | ❌ | ❌ |
Se pueden insertar elementos primitivos | ✅ | ❌ |
Si no se usa el elemento, se elimina del set | ❌ | ✅ |
Se puede convertir a array (es iterable) | ✅ | ❌ |
Propiedad .size | ✅ | ❌ |
Método .add() | ✅ | ✅ |
Método .has() | ✅ | ✅ |
Método .delete() | ✅ | ✅ |
Método .clear() | ✅ | ❌ |