Objeto `Set`
Este artículo explica el objeto Set.
Explicaremos el objeto Set con ejemplos prácticos.
YouTube Video
Objeto Set
Set es un objeto incorporado que se utiliza para manejar colecciones de valores únicos, sin duplicados. Permite escribir eliminación de duplicados y comprobaciones de existencia de manera más simple que con los arrays, y facilita la implementación de operaciones de conjuntos como unión e intersección.
Conceptos básicos: Creación y uso de Sets
Primero, veamos cómo crear un Set, agregar y eliminar elementos, comprobar la existencia y obtener su tamaño.
A continuación se muestra un patrón básico que crea un nuevo Set y demuestra add, has, delete y size.
1// Create a Set and demonstrate add, has, delete, and size
2const s = new Set();
3
4s.add(1);
5s.add(2);
6s.add(2); // duplicate, ignored
7
8console.log(s.has(1)); // true
9console.log(s.has(3)); // false
10
11s.delete(2);
12console.log(s.size); // 1
13
14console.log([...s]); // [1]
- Como se muestra en este código,
Setelimina automáticamente los valores primitivos duplicados, y puedes obtener el número de elementos usandosize.
Métodos de iteración
Set es iterable, así que puedes recorrerlo usando for...of o forEach. El orden es el orden de inserción.
Aquí hay formas típicas de usar for...of y forEach.
1// Iterate a Set with for...of and forEach
2const s = new Set(['a', 'b', 'c']);
3
4for (const v of s) {
5 console.log('for...of:', v);
6}
7
8s.forEach((value, sameValue, setRef) => {
9 // Note: second arg is same as first for Set API to match Map signature
10 console.log('forEach:', value);
11});- La firma de la función callback para
forEachesvalue, value, set(por compatibilidad con Map), pero en la práctica, normalmente solo necesitas el primer argumentovalue.
Conversión entre Arrays y Sets (útil para eliminar duplicados)
Aquí mostramos una técnica sencilla para eliminar duplicados de un array y cómo convertir un Set de nuevo en un array.
A continuación se muestra un ejemplo de cómo eliminar duplicados de un array pasándolo por un Set.
1// Deduplicate an array using Set
2const arr = [1, 2, 2, 3, 3, 3];
3const deduped = [...new Set(arr)];
4console.log(deduped); // [1, 2, 3]
5
6// Convert a Set to an array using Array.from
7const s = new Set([4, 5, 6]);
8const arrFromSet = Array.from(s);
9console.log(arrFromSet); // [4, 5, 6]
- Este patrón es corto y rápido, por lo que se utiliza con frecuencia para eliminar duplicados de arrays. Es especialmente efectivo para valores primitivos.
Objetos y manejo de referencias
Los objetos en un Set se comparan por referencia, por lo que diferentes instancias con el mismo contenido se tratan como elementos separados.
El siguiente código demuestra qué sucede cuando agregas objetos a un Set.
1// Objects are compared by reference in a Set
2const obj1 = { x: 1 };
3const obj2 = { x: 1 };
4
5const s = new Set();
6s.add(obj1);
7s.add(obj2);
8
9console.log(s.size); // 2 (different references)
10console.log(s.has(obj1)); // true
11console.log(s.has({ x: 1 })); // false (different object)
- La detección de duplicados para objetos se basa en la identidad de referencia, por lo que si deseas eliminar duplicados según el contenido del objeto, tendrás que serializarlos o procesarlos de otra manera.
Valores especiales: manejo de NaN y -0/+0
Set utiliza la regla de comparación Same-value-zero para determinar la igualdad de valores. Este método de comparación presenta las siguientes características respecto a los números:.
NaNse considera igual aNaN.+0positivo y-0negativo no se distinguen y se tratan como el mismo valor.
Por lo tanto, cuando se agregan estos valores a un Set, ocurre el siguiente comportamiento:.
1// NaN and zero behavior in Set
2const s = new Set();
3
4s.add(NaN);
5s.add(NaN);
6console.log(s.size); // 1 (NaN considered the same)
7
8s.add(+0);
9s.add(-0);
10console.log(s.size); // still 2 (NaN + 0)
11console.log([...s]); // [NaN, 0] (order may vary but only one zero)
- En una comparación normal (
NaN === NaN), devuelvefalse, pero dentro de unSet, todos los valoresNaNse consideran 'el mismo valor'. - +0 y -0 pueden distinguirse matemáticamente, pero en un
Set, simplemente se tratan como0. - Como resultado, solo queda un
NaNy un0en elSet. - La regla de comparación de
Setes similar a la deObject.is, pero no es exactamente la misma.Object.is(+0, -0)devuelvefalse, pero en unSet, se consideran idénticos. Ten en cuenta esta diferencia.
Utilidad común: operaciones de conjuntos (unión, intersección, diferencia)
Las operaciones de conjuntos se pueden escribir de manera más clara usando Set. A continuación se muestran ejemplos comunes de implementación.
Aquí tienes ejemplos de funciones para union, intersection y difference.
1// Set operations: union, intersection, difference
2function union(a, b) {
3 return new Set([...a, ...b]);
4}
5
6function intersection(a, b) {
7 return new Set([...a].filter(x => b.has(x)));
8}
9
10function difference(a, b) {
11 return new Set([...a].filter(x => !b.has(x)));
12}
13
14// Demo
15const A = new Set([1, 2, 3]);
16const B = new Set([3, 4, 5]);
17
18console.log('union', [...union(A, B)]); // [1,2,3,4,5]
19console.log('intersection', [...intersection(A, B)]); // [3]
20console.log('difference A\\B', [...difference(A, B)]); // [1,2]
- Las operaciones de conjunto se pueden escribir fácilmente usando filtros con la combinación de
Sety arrays. Cuando se trabaja con grandes conjuntos de datos, el rendimiento O(1) dehashace que las operaciones sean más rápidas.
Ejemplo práctico: encontrar diferencias entre arrays (detectar elementos añadidos/eliminados)
El siguiente ejemplo demuestra cómo usar un Set para encontrar la diferencia entre dos arrays (una lista antigua y una nueva). Esto te permite identificar qué elementos fueron añadidos y cuáles fueron eliminados.
1// Find added and removed items between two arrays
2function diffArrays(oldArr, newArr) {
3 const oldSet = new Set(oldArr);
4 const newSet = new Set(newArr);
5
6 const added = [...newSet].filter(x => !oldSet.has(x));
7 const removed = [...oldSet].filter(x => !newSet.has(x));
8
9 return { added, removed };
10}
11
12const oldList = [1, 2, 3];
13const newList = [2, 3, 4, 5];
14
15console.log(diffArrays(oldList, newList));
16// { added: [4,5], removed: [1] }
- Este método es muy conveniente para detectar diferencias en listas de ID, listas de etiquetas y situaciones similares. Es más sencillo de usar con valores primitivos.
Diferencias entre WeakSet y Set (gestión de memoria)
WeakSet es similar a Set, pero utiliza referencias débiles, lo que permite que sus elementos sean recolectados por el recolector de basura. A continuación se demuestran usos básicos de WeakSet.
1// WeakSet basics (objects only, not iterable)
2const ws = new WeakSet();
3let obj = { id: 1 };
4ws.add(obj);
5
6console.log(ws.has(obj)); // true
7
8obj = null; // Now the object is eligible for GC; WeakSet won't prevent collection
WeakSet solo puede contener objetos y no puede ser iterado. A continuación se muestran ejemplos de las limitaciones de WeakSet: solo almacena objetos y no puede iterarse.
1// WeakSet basics (objects only, not iterable)
2const ws = new WeakSet();
3
4// --- Only objects can be added ---
5try {
6 ws.add(1); // number
7} catch (e) {
8 console.log("Error: WeakSet can only store objects. Adding a number is not allowed.");
9}
10
11try {
12 ws.add("text"); // string
13} catch (e) {
14 console.log("Error: WeakSet can only store objects. Adding a string is not allowed.");
15}
16
17// --- WeakSet is not iterable ---
18try {
19 for (const value of ws) {
20 console.log(value);
21 }
22} catch (e) {
23 console.log("Error: WeakSet is not iterable. You cannot use for...of to loop over its elements.");
24}
25
26// --- Cannot convert to array ---
27try {
28 console.log([...ws]);
29} catch (e) {
30 console.log("Error: WeakSet cannot be converted to an array because it does not support iteration.");
31}
32
33// The object becomes eligible for garbage collection
34let obj = { id: 1 };
35ws.add(obj);
36obj = null;WeakSetes útil para rastrear temporalmente la presencia de objetos, pero no puedes enumerar sus elementos ni obtener su tamaño.
Rendimiento y elección de uso
Al decidir si utilizar un Set, es importante entender sus características de rendimiento y la naturaleza de tus datos.
has,addydeletenormalmente operan con un rendimiento prácticamente O(1) en promedio. Por lo tanto, en escenarios donde se verifican existencias o se eliminan duplicados con frecuencia,Setsuele ser más ventajoso que los arrays.- Ten cuidado si quieres eliminar duplicados de objetos según su contenido (valores). Como
Setcompara por referencia, una forma práctica es usar IDs u otras claves, o serializar los objetos a valores primitivos antes de usar Sets cuando se necesita una comparación basada en valores. Setes especialmente útil para mejorar la legibilidad del código en colecciones pequeñas o medianas. Por otro lado, si manejas una gran cantidad de elementos o haces conversiones frecuentes entre arrays y Sets, se recomienda realizar pruebas y mediciones reales.
Errores comunes
Set es conveniente, pero si no conoces bien sus especificaciones, puedes confundirte con comportamientos inesperados. Aquí algunos puntos típicos que debes tener en cuenta:.
- Los objetos se comparan por referencia, por lo que aunque su contenido sea igual, objetos distintos no se consideran duplicados.
Setmantiene el orden de inserción, pero no puedes acceder a los elementos por índice como en los arrays. Si deseas acceder por índice, primero convierte elSeten un array.WeakSetno puede ser enumerado y solo puede almacenar objetos. Ten en cuenta que sus aplicaciones son limitadas.NaNse trata como el mismo valor y+0y-0no se distinguen. Esto se debe a la regla de comparación Same-value-zero.
Resumen
Set es una estructura de datos conveniente que te permite manejar colecciones de valores únicos de forma intuitiva. Puedes usarlo para eliminar duplicados de arrays, realizar rápidas comprobaciones de existencia o implementar operaciones como unión e intersección con código simple y legible.
Por otro lado, dado que los objetos se comparan por referencia, necesitas medidas extras si quieres juzgar la igualdad por su contenido.
Al comprender estas características y utilizarlas adecuadamente, Set se convierte en una herramienta poderosa para mejorar la legibilidad y el mantenimiento del código.
Puedes seguir el artículo anterior utilizando Visual Studio Code en nuestro canal de YouTube. Por favor, también revisa nuestro canal de YouTube.