38. Aplicaciones de conjuntos en programación

Los conjuntos aparecen en programación cada vez que trabajamos con pertenencia, duplicados, filtros, permisos, coincidencias, diferencias y combinaciones de datos.

38.1 Introducción

La teoría de conjuntos no es solo una herramienta matemática. En programación, muchas operaciones cotidianas son aplicaciones directas de conceptos como pertenencia, unión, intersección, diferencia y cardinalidad.

JavaScript incluye la estructura Set, que permite representar colecciones de valores únicos y realizar operaciones útiles sobre ellas.

38.2 Eliminar duplicados

Una de las aplicaciones más comunes de los conjuntos es eliminar valores repetidos.

const etiquetas = ["web", "datos", "web", "api", "datos"];
const etiquetasUnicas = new Set(etiquetas);

console.log([...etiquetasUnicas]);

El conjunto conserva cada etiqueta una sola vez.

38.3 Verificar pertenencia

Un conjunto permite preguntar si un elemento está presente.

const rolesPermitidos = new Set(["admin", "editor"]);
const rolUsuario = "editor";

console.log(rolesPermitidos.has(rolUsuario));

La operación has representa la idea matemática de pertenencia.

38.4 Validación de permisos

Los permisos requeridos para una acción pueden compararse con los permisos asignados a un usuario.

function esSubconjunto(a, b) {
  return [...a].every(elemento => b.has(elemento));
}

const requeridos = new Set(["leer", "editar"]);
const asignados = new Set(["leer", "editar", "publicar"]);

console.log(esSubconjunto(requeridos, asignados));

La acción está permitida si los permisos requeridos son subconjunto de los asignados.

38.5 Unión de resultados

La unión permite combinar resultados de distintas fuentes sin repetir elementos.

function union(a, b) {
  return new Set([...a, ...b]);
}

const porTitulo = new Set(["curso-js", "curso-sql"]);
const porEtiqueta = new Set(["curso-js", "curso-html"]);

console.log([...union(porTitulo, porEtiqueta)]);

El resultado reúne todos los cursos encontrados por cualquiera de los criterios.

38.6 Intersección de criterios

La intersección permite encontrar elementos que cumplen dos condiciones al mismo tiempo.

function interseccion(a, b) {
  return new Set([...a].filter(elemento => b.has(elemento)));
}

const activos = new Set(["Ana", "Luis", "Carla"]);
const suscriptos = new Set(["Luis", "Carla", "Marta"]);

console.log([...interseccion(activos, suscriptos)]);

El resultado contiene usuarios activos y suscriptos.

38.7 Diferencia para detectar faltantes

La diferencia permite encontrar elementos que están en un conjunto pero no en otro.

function diferencia(a, b) {
  return new Set([...a].filter(elemento => !b.has(elemento)));
}

const esperados = new Set(["inicio", "perfil", "configuracion"]);
const implementados = new Set(["inicio", "perfil"]);

console.log([...diferencia(esperados, implementados)]);

El resultado muestra funcionalidades esperadas que todavía no están implementadas.

38.8 Diferencia simétrica para detectar cambios

La diferencia simétrica muestra elementos que están en una colección u otra, pero no en ambas.

function union(a, b) {
  return new Set([...a, ...b]);
}

function diferencia(a, b) {
  return new Set([...a].filter(elemento => !b.has(elemento)));
}

function diferenciaSimetrica(a, b) {
  return union(diferencia(a, b), diferencia(b, a));
}

const antes = new Set(["leer", "editar", "publicar"]);
const despues = new Set(["leer", "publicar", "eliminar"]);

console.log([...diferenciaSimetrica(antes, despues)]);

El resultado contiene permisos que cambiaron entre dos versiones.

38.9 Cardinalidad en programación

La cardinalidad de un conjunto se obtiene con size.

const visitantes = new Set(["Ana", "Luis", "Ana", "Carla"]);

console.log(visitantes.size);

La cardinalidad indica cuántos visitantes únicos hay.

38.10 Agrupar por clases

Las relaciones de equivalencia aparecen cuando agrupamos datos por una clave común.

const productos = [
  { nombre: "teclado", categoria: "perifericos" },
  { nombre: "mouse", categoria: "perifericos" },
  { nombre: "monitor", categoria: "pantallas" }
];

const porCategoria = productos.reduce((grupos, producto) => {
  const clave = producto.categoria;
  grupos[clave] ??= [];
  grupos[clave].push(producto.nombre);
  return grupos;
}, {});

console.log(porCategoria);

Cada categoría funciona como una clase de equivalencia.

38.11 Producto cartesiano para combinaciones

El producto cartesiano permite generar combinaciones de opciones.

function productoCartesiano(a, b) {
  return a.flatMap(x => b.map(y => [x, y]));
}

const talles = ["S", "M", "L"];
const colores = ["negro", "blanco"];

console.log(productoCartesiano(talles, colores));

Cada par representa una variante posible.

38.12 Relaciones entre entidades

Una relación puede representarse como un conjunto de pares ordenados.

const usuarioPermiso = [
  ["Ana", "leer"],
  ["Ana", "editar"],
  ["Luis", "leer"]
];

console.log(usuarioPermiso);

Esta estructura representa qué permisos tiene cada usuario.

38.13 Conjuntos y filtros

Un filtro construye un subconjunto de una colección original.

const usuarios = [
  { nombre: "Ana", activo: true },
  { nombre: "Luis", activo: false },
  { nombre: "Carla", activo: true }
];

const activosFiltrados = usuarios.filter(usuario => usuario.activo);

console.log(activosFiltrados);

El resultado es el subconjunto de usuarios activos.

38.14 Comparación de conjuntos

Comparar conjuntos permite verificar si dos resultados contienen los mismos elementos sin importar el orden.

function sonIguales(a, b) {
  return a.size === b.size && [...a].every(elemento => b.has(elemento));
}

const resultadoA = new Set(["a", "b", "c"]);
const resultadoB = new Set(["c", "b", "a"]);

console.log(sonIguales(resultadoA, resultadoB));

La igualdad de conjuntos no depende del orden de inserción.

38.15 Aplicaciones resumidas

Concepto Aplicación en programación Ejemplo
Pertenencia Validar existencia Rol permitido
Unión Combinar resultados Búsqueda por texto o etiqueta
Intersección Aplicar condiciones simultáneas Usuarios activos y suscriptos
Diferencia Detectar faltantes Permisos requeridos no asignados
Cardinalidad Contar únicos Visitantes distintos

38.16 Errores frecuentes

  • Usar arreglos con duplicados cuando se necesita unicidad.
  • Comparar arreglos ordenados como si fueran conjuntos.
  • Confundir unión con concatenación sin eliminar duplicados.
  • Olvidar que los objetos se comparan por referencia en un Set de JavaScript.
  • Usar conjuntos sin definir claramente el universo de datos.

38.17 Qué debes recordar de este tema

  • Los conjuntos sirven para trabajar con valores únicos.
  • Set permite verificar pertenencia con has.
  • Unión, intersección y diferencia aparecen en filtros, permisos y búsquedas.
  • La cardinalidad se obtiene con size.
  • El producto cartesiano permite generar combinaciones.
  • Muchas estructuras de programación pueden interpretarse con ideas de conjuntos.

38.18 Conclusión

La teoría de conjuntos ofrece un lenguaje práctico para resolver problemas de programación. Permite modelar pertenencia, unicidad, filtros, combinaciones, relaciones y comparaciones de datos.

En el próximo tema estudiaremos aplicaciones de conjuntos en estructuras de datos.