Conjuntos con Set - parte 1

Básico
JavaScript
JavaScript
Actualizado: 04/05/2026

Diagrama: tutorial-javascript-conjuntos-set-parte-1

Fundamentos y características de la estructura Set

La estructura Set es una de las adiciones más útiles que llegaron con ECMAScript 2015 (ES6) a JavaScript. Un Set representa una colección de valores únicos, lo que significa que no puede contener elementos duplicados. Esta característica fundamental lo diferencia de los arrays tradicionales y lo convierte en una herramienta extremadamente valiosa para ciertas operaciones.

Características principales

Los Set en JavaScript poseen varias características distintivas que los hacen especialmente útiles:

1. Unicidad de elementos: La característica más importante de un Set es que cada valor puede aparecer solo una vez. Cualquier intento de añadir un elemento duplicado será simplemente ignorado.

const colores = new Set();
colores.add('rojo');
colores.add('azul');
colores.add('rojo'); // Este valor se ignora
console.log(colores.size); // 2
console.log([...colores]); // ['rojo', 'azul']

2. Preservación del orden de inserción: Los Set mantienen el orden en que los elementos fueron insertados, similar a los arrays.

 const numeros = new Set([1, 5, 3, 9, 4]);
 console.log([...numeros]); // [1, 5, 3, 9, 4]

3. Tipos de valores admitidos: Un Set puede almacenar cualquier tipo de valor, incluyendo primitivos y referencias a objetos.

const mixedSet = new Set();
mixedSet.add(42);
mixedSet.add('texto');
mixedSet.add(true);
mixedSet.add({ id: 1, name: 'Object' });
mixedSet.add(function() { return 'Hello'; });
console.log(mixedSet.size); // 5

4. Comparación de valores: Los Set utilizan el algoritmo "SameValueZero" para comparar valores, similar a === pero con una diferencia clave: en un Set, NaN se considera igual a sí mismo.

const numerosEspeciales = new Set();
numerosEspeciales.add(NaN);
numerosEspeciales.add(NaN); // Ignorado porque NaN === NaN en Sets

console.log(numerosEspeciales.size); // 1

5. Iterabilidad: Los Set son iterables por defecto, lo que significa que pueden usarse con bucles for...of y son compatibles con el operador spread (...).


const letras = new Set(['a', 'b', 'c']);

// Iteración con for...of
for (const letra of letras) {
  console.log(letra); // 'a', 'b', 'c'
}

// Uso del operador spread
const arrayDeLetras = [...letras];

console.log(arrayDeLetras); // ['a', 'b', 'c']

Creación de Sets

Existen varias formas de crear un Set en JavaScript:

1. Constructor vacío:

const conjuntoVacio = new Set();
console.log(conjuntoVacio.size); // 0

2. A partir de un iterable:

// A partir de un array
const frutasUnicas = new Set(['manzana', 'naranja', 'manzana', 'plátano']);
console.log(frutasUnicas.size); // 3 (el duplicado 'manzana' se elimina)

// A partir de una cadena (cada carácter se convierte en un elemento)
const letrasUnicas = new Set('mississippi');
console.log([...letrasUnicas]); // ['m', 'i', 's', 'p']

Comportamiento con objetos y referencias

Es importante entender cómo los Set manejan las referencias a objetos. Dos objetos con el mismo contenido pero diferentes referencias se consideran elementos distintos:

const set = new Set();

set.add({});
set.add({});
console.log(set.size); // 2, porque son dos referencias diferentes

const obj = { id: 1 };
set.add(obj);
set.add(obj); // Misma referencia, se ignora
console.log(set.size); // 3

Conversiones entre Set y Array

La conversión entre Set y arrays es una operación muy común y útil:

De Array a Set (eliminar duplicados):

const arrayConDuplicados = [1, 2, 3, 1, 2, 5];
const arraySinDuplicados = [...new Set(arrayConDuplicados)];

console.log(arraySinDuplicados); // [1, 2, 3, 5]

De Set a Array:

const miSet = new Set(['a', 'b', 'c']);

// Usando el operador spread
const array1 = [...miSet];

// Usando Array.from()
const array2 = Array.from(miSet);

console.log(array1); // ['a', 'b', 'c']
console.log(array2); // ['a', 'b', 'c']

Rendimiento y casos de uso

Los Set ofrecen un rendimiento superior en ciertos escenarios:

  • Búsqueda de elementos: La operación has() en un Set tiene una complejidad de tiempo O(1), mientras que buscar en un array con includes() es O(n).
// Con un conjunto grande de datos, esto es mucho más rápido
const numerosGrandes = new Set([/* miles de números */]);
const existe = numerosGrandes.has(42); // O(1)

// Versus un array
const arrayGrande = [/* miles de números */];
const existeEnArray = arrayGrande.includes(42); // O(n)

Eliminación de duplicados: Como hemos visto, convertir un array a Set y viceversa es la forma más eficiente de eliminar duplicados.

  • Registro de valores únicos: Cuando necesitas mantener un registro de elementos únicos que has procesado.
// Seguimiento de IDs de usuario que han iniciado sesión
const usuariosActivos = new Set();

function registrarActividad(userId) {
  usuariosActivos.add(userId);
  console.log(`Usuarios activos hoy: ${usuariosActivos.size}`);
}

registrarActividad('user123');
registrarActividad('user456');
registrarActividad('user123'); // Usuario repetido, no incrementa el contador
  • Comprobación de pertenencia: Verificar si un elemento existe en una colección.
const palabrasProhibidas = new Set(['spam', 'virus', 'malware']);

function esSeguro(texto) {
  const palabras = texto.toLowerCase().split(' ');
  return !palabras.some(palabra => palabrasProhibidas.has(palabra));
}

console.log(esSeguro('mensaje normal')); // true
console.log(esSeguro('posible spam detectado')); // false

Los Set en JavaScript proporcionan una forma elegante y eficiente de trabajar con colecciones de valores únicos, ofreciendo un rendimiento optimizado para operaciones como la búsqueda y eliminación de duplicados. Su integración con otras características modernas de JavaScript, como la iterabilidad y la compatibilidad con el operador spread, los convierte en una herramienta fundamental en el arsenal de cualquier desarrollador JavaScript.

Métodos y propiedades fundamentales de los Sets

Los objetos Set en JavaScript proporcionan una interfaz rica y concisa para manipular colecciones de valores únicos. Conocer sus métodos y propiedades es esencial para aprovechar al máximo esta estructura de datos. Veamos en detalle cada uno de estos componentes fundamentales.

Propiedades principales

Set.prototype.size

La propiedad size es de solo lectura y devuelve el número de elementos únicos en un Set:

const tecnologias = new Set(['JavaScript', 'TypeScript', 'React', 'Node.js']);
console.log(tecnologias.size); // 4

tecnologias.add('JavaScript'); // Intento de añadir un duplicado
console.log(tecnologias.size); // Sigue siendo 4

A diferencia de los arrays con su propiedad length, no es posible modificar directamente el valor de size:

const miSet = new Set([1, 2, 3]);
miSet.size = 10; // No tiene efecto
console.log(miSet.size); // Sigue siendo 3

Métodos para añadir y eliminar elementos

add()

El método add() inserta un nuevo elemento en el Set y devuelve el Set modificado, lo que permite encadenar llamadas:

const carrito = new Set();

carrito.add('Producto 1')
       .add('Producto 2')
       .add('Producto 3');

console.log(carrito.size); // 3

Si intentamos añadir un elemento que ya existe, la operación se ignora silenciosamente:

const numeros = new Set();
numeros.add(42);
numeros.add(42); // No tiene efecto

console.log(numeros.size); // 1

delete()

El método delete() elimina un elemento específico del Set y devuelve un booleano indicando si la operación tuvo éxito:

const frutas = new Set(['manzana', 'naranja', 'plátano']);

const eliminadaNaranja = frutas.delete('naranja'); // true
const eliminadaUva = frutas.delete('uva');         // false (no existía)

console.log(frutas); // Set(2) { 'manzana', 'plátano' }
console.log(eliminadaNaranja, eliminadaUva); // true false

A diferencia de add(), el método delete() no se puede encadenar efectivamente porque devuelve un booleano en lugar del Set modificado.

clear()

El método clear() elimina todos los elementos de un Set, dejándolo vacío:

const colores = new Set(['rojo', 'verde', 'azul']);
console.log(colores.size); // 3

colores.clear();
console.log(colores.size); // 0

Este método es útil cuando necesitamos reiniciar un Set sin tener que crear una nueva instancia.

Métodos para verificar la existencia de elementos

has()

El método has() comprueba si un valor específico existe en el Set y devuelve un booleano:

const permisosUsuario = new Set(['leer', 'escribir']);

console.log(permisosUsuario.has('leer'));     // true
console.log(permisosUsuario.has('eliminar')); // false

La operación has() es extremadamente eficiente con una complejidad de tiempo O(1), lo que hace que los Sets sean ideales para verificaciones rápidas de pertenencia:

// Verificación de palabras en un diccionario
const diccionario = new Set(['casa', 'perro', 'libro', /* miles de palabras */]);

function palabraExiste(palabra) {
  return diccionario.has(palabra.toLowerCase());
}

console.log(palabraExiste('Casa')); // true
console.log(palabraExiste('Elefante')); // false (asumiendo que no está en el diccionario)

Métodos de iteración

forEach()

El método forEach() ejecuta una función para cada elemento del Set, similar a Array.prototype.forEach():

const ciudades = new Set(['Madrid', 'Barcelona', 'Valencia']);

ciudades.forEach((ciudad, valorDuplicado, set) => {
  console.log(`Visitando ${ciudad}`);
  // Nota: en Sets, el segundo parámetro (valorDuplicado) es igual al primero
  // porque los Sets no tienen índices ni claves
});

// Salida:
// Visitando Madrid
// Visitando Barcelona
// Visitando Valencia

Es importante notar que, a diferencia de los arrays, el segundo parámetro de la función callback es el mismo valor que el primero, ya que los Sets no tienen índices:

const numeros = new Set([1, 2, 3]);

numeros.forEach((valor, valorDuplicado) => {
  console.log(`Valor: ${valor}, Duplicado: ${valorDuplicado}`);
});

// Salida:
// Valor: 1, Duplicado: 1
// Valor: 2, Duplicado: 2
// Valor: 3, Duplicado: 3

Métodos de iteración integrados

Los Sets son iterables por naturaleza y proporcionan tres métodos que devuelven iteradores:

  • values(): Devuelve un nuevo iterador con los valores del Set:
const letras = new Set(['a', 'b', 'c']);
const iterador = letras.values();

console.log(iterador.next().value); // 'a'
console.log(iterador.next().value); // 'b'
console.log(iterador.next().value); // 'c'
  • keys(): Idéntico a values() en Sets (a diferencia de Maps, donde las claves y valores son distintos):
const numeros = new Set([1, 2, 3]);
const iterador = numeros.keys();

for (const num of iterador) {
  console.log(num);
}
// Salida: 1, 2, 3
  • entries(): Devuelve un iterador con pares [valor, valor] para cada elemento:
const frutas = new Set(['manzana', 'plátano']);
const iterador = frutas.entries();

for (const entry of iterador) {
  console.log(entry);
}
// Salida:
// ['manzana', 'manzana']
// ['plátano', 'plátano']

El método entries() puede parecer redundante para Sets, pero mantiene una interfaz consistente con otras colecciones como Map.

Iteración directa con for...of

Dado que los Sets son iterables, podemos usar directamente un bucle for...of:

const animales = new Set(['perro', 'gato', 'conejo']);

for (const animal of animales) {
  console.log(`Animal: ${animal}`);
}
// Salida:
// Animal: perro
// Animal: gato
// Animal: conejo

Por defecto, iterar sobre un Set es equivalente a usar el método values().

Conversiones y manipulaciones avanzadas

Filtrado de elementos

Podemos filtrar elementos de un Set convirtiéndolo primero a un array:

const numeros = new Set([1, 2, 3, 4, 5, 6]);

// Filtrar solo números pares
const numerosPares = new Set(
  [...numeros].filter(num => num % 2 === 0)
);

console.log([...numerosPares]); // [2, 4, 6]

Mapeo de valores

De manera similar, podemos transformar los valores de un Set:

const numeros = new Set([1, 2, 3]);

// Elevar al cuadrado cada número
const cuadrados = new Set(
  [...numeros].map(num => num * num)
);

console.log([...cuadrados]); // [1, 4, 9]

Combinación con desestructuración

La combinación de Sets con la desestructuración de arrays puede ser muy útil:

const [primerElemento, segundoElemento] = new Set(['a', 'b', 'c']);

console.log(primerElemento);  // 'a'
console.log(segundoElemento); // 'b'

Casos de uso prácticos

Seguimiento de elementos únicos visitados

function rastrearPaginasVisitadas() {
  const paginasVisitadas = new Set();
  
  return {
    registrarVisita(pagina) {
      paginasVisitadas.add(pagina);
      return paginasVisitadas.size;
    },
    fueVisitada(pagina) {
      return paginasVisitadas.has(pagina);
    },
    obtenerTotalVisitasUnicas() {
      return paginasVisitadas.size;
    },
    obtenerListado() {
      return [...paginasVisitadas];
    }
  };
}

const rastreador = rastrearPaginasVisitadas();
rastreador.registrarVisita('/home');
rastreador.registrarVisita('/products');
rastreador.registrarVisita('/home'); // Duplicado

console.log(rastreador.fueVisitada('/about')); // false
console.log(rastreador.obtenerTotalVisitasUnicas()); // 2
console.log(rastreador.obtenerListado()); // ['/home', '/products']

Caché de resultados

function crearCacheFunciones() {
  const cache = new Set();
  
  return {
    ejecutarUnaVez(fn) {
      if (!cache.has(fn)) {
        cache.add(fn);
        fn();
      }
    },
    limpiarCache() {
      cache.clear();
    }
  };
}

const ejecutor = crearCacheFunciones();

const saludar = () => console.log('¡Hola!');
ejecutor.ejecutarUnaVez(saludar); // Imprime: ¡Hola!
ejecutor.ejecutarUnaVez(saludar); // No hace nada, ya se ejecutó

ejecutor.limpiarCache();
ejecutor.ejecutarUnaVez(saludar); // Imprime: ¡Hola! (de nuevo)

Los métodos y propiedades de los Sets en JavaScript proporcionan una interfaz completa para trabajar con colecciones de valores únicos. Su simplicidad y eficiencia los convierten en una herramienta fundamental para muchos escenarios de programación, desde la eliminación de duplicados hasta la implementación de algoritmos que requieren verificaciones rápidas de pertenencia.

Alan Sastre - Autor del tutorial

Alan Sastre

Ingeniero de Software y formador, CEO en CertiDevs

Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, JavaScript es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.

Más tutoriales de JavaScript

Explora más contenido relacionado con JavaScript y continúa aprendiendo con nuestros tutoriales gratuitos.

Aprendizajes de esta lección

  • Comprender qué es un Set en JavaScript y cómo difiere de otras estructuras de datos como Arrays.
  • Conocer las diferentes formas de crear un Set utilizando el constructor Set y cómo inicializarlo con valores.
  • Aprender a agregar y eliminar elementos en un Set utilizando los métodos .add(valor) y .delete(valor).
  • Entender cómo verificar si un elemento existe en un Set utilizando el método .has(valor).
  • Saber cómo obtener el tamaño de un Set utilizando la propiedad .size.
  • Familiarizarse con las opciones para iterar sobre los elementos de un Set mediante un bucle for...of o el método .forEach().
  • Conocer cómo convertir un Set en un Array utilizando el operador de extensión ... o el método Array.from().
  • Entender cómo convertir un Array en un Set simplemente pasándolo al constructor Set.
  • Reconocer la utilidad de los Sets en JavaScript para manejar conjuntos únicos de datos y realizar operaciones eficientes sobre ellos.
  • Conocer los nuevos métodos nativos de ES2025 (intersection, union, difference, symmetricDifference, isSubsetOf, isSupersetOf, isDisjointFrom) para operaciones entre conjuntos.