Ir al contenido principal

Conjuntos: operaciones y usos

Introducción

Los conjuntos en Python son colecciones desordenadas de elementos únicos. Comparten características con los conjuntos matemáticos, lo que los hace especialmente útiles para operaciones como la unión, intersección o diferencia. A diferencia de las listas o tuplas, los conjuntos no permiten elementos duplicados y no mantienen un orden específico, lo que los convierte en estructuras muy eficientes para ciertas tareas. En este artículo, aprenderemos qué son los conjuntos, cómo trabajar con ellos y qué operaciones podemos realizar.

Creación de conjuntos

Existen dos formas principales de crear conjuntos en Python:

# Usando llaves
colores = {"rojo", "verde", "azul"}
print(colores)  # Puede mostrar {'verde', 'rojo', 'azul'} (orden no garantizado)

# Usando la función set()
numeros = set([1, 2, 3, 2, 1])  # Los duplicados se eliminan automáticamente
print(numeros)  # Muestra {1, 2, 3}

# Conjunto vacío (¡importante! {} crea un diccionario vacío, no un conjunto)
conjunto_vacio = set()
print(conjunto_vacio)  # Muestra set()

Es importante tener en cuenta que no podemos crear un conjunto vacío utilizando {}, ya que esto crea un diccionario vacío. Debemos usar set() en su lugar.

Características de los conjuntos

Los conjuntos tienen varias características distintivas:

  1. Elementos únicos: No permiten duplicados

    numeros = {1, 2, 3, 2, 1}
    print(numeros)  # Muestra {1, 2, 3} - los duplicados se eliminan
    
  2. Desordenados: No tienen un orden específico

    conjunto = {3, 1, 2}
    # El orden de impresión puede variar
    print(conjunto)  # Podría mostrar {1, 2, 3} o cualquier otra permutación
    
  3. Elementos inmutables: Solo pueden contener elementos inmutables como números, cadenas y tuplas (no listas o diccionarios)

    # Válido - todos los elementos son inmutables
    conjunto_valido = {1, "hola", (1, 2)}
    
    # Inválido - las listas son mutables
    # conjunto_invalido = {1, [2, 3]}  # Esto provocaría un error TypeError
    

Operaciones básicas con conjuntos

Añadir y eliminar elementos

frutas = {"manzana", "naranja"}

# Añadir un elemento
frutas.add("plátano")
print(frutas)  # {'manzana', 'naranja', 'plátano'}

# Eliminar un elemento (provoca error si no existe)
frutas.remove("naranja")
print(frutas)  # {'manzana', 'plátano'}

# Eliminar un elemento (no provoca error si no existe)
frutas.discard("pera")  # No hace nada porque "pera" no está en el conjunto
print(frutas)  # {'manzana', 'plátano'}

# Extraer y eliminar un elemento aleatorio
elemento = frutas.pop()
print(elemento)  # Podría ser 'manzana' o 'plátano'
print(frutas)  # El conjunto sin el elemento extraído

# Eliminar todos los elementos
frutas.clear()
print(frutas)  # set()

Comprobación de pertenencia

animales = {"perro", "gato", "pez"}

# Comprobar si un elemento está en el conjunto
print("gato" in animales)  # True
print("león" in animales)  # False

Operaciones matemáticas con conjuntos

Las operaciones matemáticas son una de las características más potentes de los conjuntos en Python:

Unión (elementos que están en cualquiera de los conjuntos)

grupo_a = {1, 2, 3}
grupo_b = {3, 4, 5}

# Usando el operador |
union = grupo_a | grupo_b
print(union)  # {1, 2, 3, 4, 5}

# Usando el método union()
union = grupo_a.union(grupo_b)
print(union)  # {1, 2, 3, 4, 5}

Intersección (elementos comunes a ambos conjuntos)

grupo_a = {1, 2, 3}
grupo_b = {3, 4, 5}

# Usando el operador &
interseccion = grupo_a & grupo_b
print(interseccion)  # {3}

# Usando el método intersection()
interseccion = grupo_a.intersection(grupo_b)
print(interseccion)  # {3}

Diferencia (elementos en el primer conjunto pero no en el segundo)

grupo_a = {1, 2, 3}
grupo_b = {3, 4, 5}

# Usando el operador -
diferencia = grupo_a - grupo_b
print(diferencia)  # {1, 2}

# Usando el método difference()
diferencia = grupo_a.difference(grupo_b)
print(diferencia)  # {1, 2}

Diferencia simétrica (elementos que están en uno u otro conjunto, pero no en ambos)

grupo_a = {1, 2, 3}
grupo_b = {3, 4, 5}

# Usando el operador ^
dif_simetrica = grupo_a ^ grupo_b
print(dif_simetrica)  # {1, 2, 4, 5}

# Usando el método symmetric_difference()
dif_simetrica = grupo_a.symmetric_difference(grupo_b)
print(dif_simetrica)  # {1, 2, 4, 5}

Verificación de subconjuntos y superconjuntos

numeros = {1, 2, 3, 4, 5}
pares = {2, 4}
impares = {1, 3, 5}

# Comprobar si es un subconjunto (todos los elementos de pares están en numeros)
print(pares.issubset(numeros))  # True
print(pares <= numeros)  # True (operador de subconjunto)

# Comprobar si es un superconjunto (todos los elementos de pares están en numeros)
print(numeros.issuperset(pares))  # True
print(numeros >= pares)  # True (operador de superconjunto)

# Comprobar si son disjuntos (no tienen elementos en común)
print(pares.isdisjoint(impares))  # True (no comparten elementos)

Casos de uso prácticos

Los conjuntos son especialmente útiles en ciertos escenarios:

Eliminación de duplicados

# Convertir una lista con duplicados a un conjunto elimina los duplicados
numeros_duplicados = [1, 2, 2, 3, 4, 3, 5]
numeros_unicos = set(numeros_duplicados)
print(numeros_unicos)  # {1, 2, 3, 4, 5}

# Si necesitamos volver a una lista, podemos convertir de nuevo
lista_sin_duplicados = list(numeros_unicos)
print(lista_sin_duplicados)  # [1, 2, 3, 4, 5] (aunque el orden puede variar)

Encontrar elementos comunes o únicos entre colecciones

alumnos_matematicas = {"Ana", "Pedro", "Luis", "María"}
alumnos_fisica = {"Pedro", "María", "Carmen", "Jorge"}

# Estudiantes que toman ambas asignaturas
ambas_asignaturas = alumnos_matematicas & alumnos_fisica
print(ambas_asignaturas)  # {'Pedro', 'María'}

# Estudiantes que solo toman matemáticas
solo_matematicas = alumnos_matematicas - alumnos_fisica
print(solo_matematicas)  # {'Ana', 'Luis'}

# Todos los estudiantes únicos
todos_los_estudiantes = alumnos_matematicas | alumnos_fisica
print(todos_los_estudiantes)  # {'Ana', 'Pedro', 'Luis', 'María', 'Carmen', 'Jorge'}

Comprobación de pertenencia eficiente

Los conjuntos son mucho más eficientes que las listas para comprobar si un elemento está presente:

# Para listas largas, buscar en un conjunto es mucho más rápido
numeros_grandes = list(range(10000))
conjunto_numeros = set(numeros_grandes)

# Verificación de pertenencia (más eficiente en conjuntos que en listas)
numero_buscado = 9999

# Ambos devuelven True, pero el conjunto es mucho más rápido
print(numero_buscado in numeros_grandes)  # Operación lenta en listas largas
print(numero_buscado in conjunto_numeros)  # Operación rápida incluso con conjuntos grandes

Comprensión de conjuntos

Al igual que con las listas, podemos usar comprensiones para crear conjuntos de manera concisa:

# Crear un conjunto de cuadrados de números del 0 al 9
cuadrados = {x**2 for x in range(10)}
print(cuadrados)  # {0, 1, 4, 9, 16, 25, 36, 49, 64, 81}

# Crear un conjunto de vocales de una cadena
texto = "programacion en python"
vocales = {letra for letra in texto if letra in "aeiou"}
print(vocales)  # {'a', 'e', 'i', 'o', 'u'}

Resumen

Los conjuntos son estructuras de datos versátiles en Python que nos permiten trabajar con colecciones de elementos únicos y aplicar operaciones matemáticas de conjuntos. Son especialmente útiles cuando necesitamos eliminar duplicados, realizar operaciones de unión, intersección o diferencia, o comprobar la pertenencia de elementos de manera eficiente. Aunque tienen limitaciones como no mantener un orden específico o no poder contener elementos mutables, los conjuntos son una herramienta poderosa que complementa a las listas, tuplas y diccionarios en Python.

En el siguiente artículo exploraremos los métodos comunes de las diferentes estructuras de datos en Python, lo que nos permitirá aprovechar al máximo estas potentes herramientas.