CAP 11 · LEC 01·Estructuras de datos modernas

set y frozenset: colecciones únicas con operaciones de conjuntos

Un set elimina duplicados automáticamente y soporta operaciones matemáticas de conjuntos: unión, intersección, diferencia. frozenset es su versión inmutable, que puede usarse como clave de dict.

● INTERMEDIO8 min lectura4 ejerciciospor Fernando Herrera · actualizado mayo de 2026
¿Encontraste un error o algo que mejorar?Editá esta lección en GitHub →

Crear sets y propiedades fundamentales

Un set es una colección desordenada de elementos únicos. Se crea con llaves {} o con set(). A diferencia del dict, no tiene clave-valor — solo valores. Los duplicados se eliminan automáticamente.

# Crear un set con literales colores = {"rojo", "verde", "azul", "rojo"} # "rojo" duplicado print(colores) # {'rojo', 'verde', 'azul'} — un solo "rojo" # Crear desde una lista (elimina duplicados) numeros = set([1, 2, 2, 3, 3, 3, 4]) print(numeros) # {1, 2, 3, 4} # set() sobre un string — letras únicas letras = set("mississippi") print(letras) # {'m', 'i', 's', 'p'} # Propiedades clave print(len(colores)) # 3 print("rojo" in colores) # True print("negro" in colores) # False # Añadir y eliminar elementos colores.add("negro") colores.discard("verde") # no lanza error si no existe print(colores) # {'rojo', 'azul', 'negro'}
Salida{'rojo', 'verde', 'azul'} {1, 2, 3, 4} {'m', 'i', 's', 'p'} 3 True False {'rojo', 'azul', 'negro'}
set() vacío, no {}

{} crea un dict vacío, no un set vacío. Para un set vacío usa siempre set().

Operaciones de conjuntos: |, &, -, ^

Los sets implementan todas las operaciones matemáticas de conjuntos con operadores simbólicos. Esto los hace perfectos para comparar colecciones y encontrar relaciones entre ellas.

python_devs = {"Ana", "Carlos", "Diana", "Eva"} js_devs = {"Carlos", "Eva", "Felipe", "Gema"} # Unión (|): todos los elementos de ambos sets todos = python_devs | js_devs print(todos) # {'Ana', 'Carlos', 'Diana', 'Eva', 'Felipe', 'Gema'} # Intersección (&): solo los que están en ambos ambos = python_devs & js_devs print(ambos) # {'Carlos', 'Eva'} # Diferencia (-): los de A que no están en B solo_python = python_devs - js_devs print(solo_python) # {'Ana', 'Diana'} # Diferencia simétrica (^): los que están en uno u otro, pero no en ambos solo_uno = python_devs ^ js_devs print(solo_uno) # {'Ana', 'Diana', 'Felipe', 'Gema'} # Versiones con métodos (equivalentes a los operadores) print(python_devs.union(js_devs)) # igual que | print(python_devs.intersection(js_devs)) # igual que & print(python_devs.difference(js_devs)) # igual que - # Subconjunto e superconjunto a = {1, 2} b = {1, 2, 3, 4} print(a.issubset(b)) # True — a ⊆ b print(b.issuperset(a)) # True — b ⊇ a print(a.isdisjoint({5, 6})) # True — sin elementos comunes
Salida{'Ana', 'Carlos', 'Diana', 'Eva', 'Felipe', 'Gema'} {'Carlos', 'Eva'} {'Ana', 'Diana'} {'Ana', 'Diana', 'Felipe', 'Gema'} True True True

frozenset como clave de dict

frozenset es la versión inmutable de set. No se puede modificar después de crearse, lo que lo hace hashable — puede usarse como clave de dict o como elemento de otro set.

# frozenset: inmutable y hashable fs = frozenset([1, 2, 3]) print(fs) # frozenset({1, 2, 3}) print(type(fs)) # <class 'frozenset'> # hash(frozenset) funciona — no así con set normal print(hash(fs)) # algún entero # Usar frozenset como clave de diccionario # Caso real: agrupar combinaciones sin orden (A-B == B-A) partidos = { frozenset({"España", "Francia"}): 2, frozenset({"Alemania", "Italia"}): 1, frozenset({"España", "Alemania"}): 0, } # Buscar por cualquier orden de los dos equipos clave = frozenset({"Francia", "España"}) print(partidos[clave]) # 2 # frozenset dentro de un set grupos = {frozenset({"A", "B"}), frozenset({"C", "D"})} print(grupos) # {frozenset({'A', 'B'}), frozenset({'C', 'D'})} # Las operaciones de conjuntos funcionan igual a = frozenset({1, 2, 3}) b = frozenset({2, 3, 4}) print(a & b) # frozenset({2, 3})
Salidafrozenset({1, 2, 3}) <class 'frozenset'> 2 {frozenset({'A', 'B'}), frozenset({'C', 'D'})} frozenset({2, 3})
setfrozenset
Mutable: add(), discard(), pop()Inmutable: no cambia tras crearse
No hashable → no puede ser clave de dictHashable → puede ser clave de dict o elemento de set
Ideal para colecciones que cambianIdeal para colecciones constantes y como clave

Cuándo usar set vs lista

La elección entre set y lista afecta tanto la semántica como el rendimiento. Los sets tienen búsqueda O(1); las listas tienen búsqueda O(n).

import time # Búsqueda en lista: O(n) lista_grande = list(range(1_000_000)) start = time.perf_counter() resultado = 999_999 in lista_grande print(f"Lista: {time.perf_counter() - start:.4f}s") # ~0.01s # Búsqueda en set: O(1) set_grande = set(range(1_000_000)) start = time.perf_counter() resultado = 999_999 in set_grande print(f"Set: {time.perf_counter() - start:.6f}s") # ~0.000001s # Caso 1: eliminar duplicados de una lista emails_con_duplicados = ["ana@x.com", "carlos@x.com", "ana@x.com", "diana@x.com"] emails_unicos = list(set(emails_con_duplicados)) # Caso 2: verificar membresía frecuente palabras_permitidas = {"admin", "user", "guest", "moderator"} rol = "admin" if rol in palabras_permitidas: # O(1) — perfecto para esto print("Acceso permitido") # Cuando NO usar set: cuando el orden importa o necesitas duplicados ranking = ["primer", "segundo", "segundo", "tercero"] # los duplicados son intencionales # ranking como set perdería la posición y los empates
SalidaLista: 0.0089s Set: 0.000001s Acceso permitido
Regla práctica

Usa set cuando necesites unicidad, operaciones de conjuntos o búsquedas rápidas de membresía. Usa lista cuando el orden importa, los duplicados son significativos, o necesitas acceso por índice.

Practica