Módulo 07: Diccionarios y Sets

Idea central

Un diccionario (dict) es una tabla hash que mapea claves a valores en tiempo O(1). Un set es una colección de claves únicas sin valores. Son las estructuras más importantes para resolver problemas de tipo NeetCode/LeetCode: contar frecuencias, detectar duplicados, agrupar, buscar en O(1).


Qué aprendes

ConceptoPara qué sirve
dict — crear y accederAlmacenar pares clave→valor, buscar en O(1)
.get(clave, default)Acceder sin lanzar KeyError
.keys() / .values() / .items()Iterar sobre partes del dict
clave in dictComprobar existencia en O(1)
Añadir / actualizar entradasConstruir dicts dinámicamente
set — elementos únicosEliminar duplicados, test de pertenencia O(1)
`(unión) y&` (intersección)
collections.CounterContar frecuencias de forma idiomática

C vs Python

El equivalente en C de un diccionario es una tabla hash manual (o un array paralelo clave-valor), que requiere ~40 líneas. Python lo da en una línea.

OperaciónCPython
Crear tabla clave→valorstruct Entry { char *key; int val; }; (implementación manual)d = {"a": 1, "b": 2}
Leer valorhash_get(table, "a") (función propia)d["a"] o d.get("a", 0)
Escribir/actualizarhash_set(table, "a", 3)d["a"] = 3
Comprobar existenciahash_contains(table, "a")"a" in d
Iterar paresbucle sobre array de Entryfor k, v in d.items():
Conjunto sin duplicadosarray + búsqueda lineal O(n)s = {1, 2, 3} — O(1) test
Unión / intersecciónbucles manualess1 | s2, s1 & s2
Contar frecuenciasfreq[c - 'a']++ (solo chars)Counter(lista) — cualquier tipo

Explicación

Dict — patrón y sintaxis

# Crear
d = {}                        # dict vacío
d = {"nombre": "Ana", "edad": 25}
 
# Leer — dos formas
print(d["nombre"])            # KeyError si no existe
print(d.get("altura", 0))     # devuelve 0 si no existe (nunca lanza error)
 
# Escribir / actualizar
d["edad"] = 26                # actualiza si existe, crea si no
d["ciudad"] = "Madrid"        # nueva clave
 
# Comprobar existencia
if "nombre" in d:
    print("tiene nombre")
 
# Iterar
for clave in d:               # itera claves
    print(clave, d[clave])
 
for clave, valor in d.items():  # itera pares (más legible)
    print(f"{clave}: {valor}")
 
print(list(d.keys()))         # ["nombre", "edad", "ciudad"]
print(list(d.values()))       # ["Ana", 26, "Madrid"]

Patrón frecuencia (el más usado en entrevistas):

# Contar sin Counter
freq = {}
for x in ["a", "b", "a", "c", "b", "a"]:
    freq[x] = freq.get(x, 0) + 1
# freq == {"a": 3, "b": 2, "c": 1}

Set — patrón y sintaxis

s = {1, 2, 3}        # set literal  (¡{} solo crea dict vacío, no set!)
s = set()            # set vacío — OBLIGATORIO usar set()
 
s.add(4)             # añadir
s.remove(4)          # eliminar (KeyError si no existe)
s.discard(99)        # eliminar sin error
 
print(2 in s)        # True — O(1)
 
a = {1, 2, 3}
b = {2, 3, 4}
print(a | b)         # {1, 2, 3, 4}  unión
print(a & b)         # {2, 3}        intersección
print(a - b)         # {1}           diferencia

collections.Counter

from collections import Counter
 
palabras = ["sol", "luna", "sol", "sol", "luna"]
c = Counter(palabras)
print(c)                    # Counter({'sol': 3, 'luna': 2})
print(c["sol"])             # 3
print(c.most_common(1))     # [('sol', 3)]

Counter es un dict con comportamiento extra: devuelve 0 para claves inexistentes (no KeyError).


Worked example

Problema: dada una frase, agrupar las palabras por su primera letra y mostrarlas ordenadas.

Entrada: "oso ardilla abeja ballena aguila"
Salida:
a: abeja, aguila, ardilla
b: ballena
o: oso

Paso 1 — pensar la estructura: Necesito dict donde cada clave es una letra y el valor es una lista de palabras.

Paso 2 — código:

frase = "oso ardilla abeja ballena aguila"
palabras = frase.split()           # ["oso", "ardilla", ...]
 
grupos = {}
for palabra in palabras:
    inicial = palabra[0]           # primera letra
    if inicial not in grupos:
        grupos[inicial] = []       # crear lista vacía la primera vez
    grupos[inicial].append(palabra)
 
# Ordenar el dict por clave para salida limpia
for letra in sorted(grupos):
    palabras_ordenadas = sorted(grupos[letra])
    print(f"{letra}: {', '.join(palabras_ordenadas)}")

Paso 3 — trazado mental:

  • "oso" → inicial "o"grupos["o"] = ["oso"]
  • "ardilla""a"grupos["a"] = ["ardilla"]
  • "abeja""a"grupos["a"] = ["ardilla", "abeja"]

Paso 4 — salida:

a: abeja, aguila, ardilla
b: ballena
o: oso

Errores típicos de Python

#ErrorEjemplo incorrectoCorrección
1KeyError al leer clave inexistented["x"] cuando "x" no estád.get("x", valor_por_defecto)
2Crear set vacío con {}s = {} → es un dict, no sets = set()
3Olvidar que input() devuelve strn = input() luego freq[n + 1]convertir primero si es número
4Iterar el dict mientras se modificafor k in d: del d[k]RuntimeErroriterar list(d.keys()) o construir nuevo dict
5Indentación dentro del forcuerpo del bucle al nivel 0todo el cuerpo debe estar sangrado 4 espacios

Ejercicios

Todos los archivos están en practica/07-diccionarios-sets/.

#EnunciadoDificultadSalida de ejemplo
01Cuenta la frecuencia de cada palabra en una frase introducida por el usuario. Muestra cada palabra y su cuenta.(facil) Verdehola: 2, mundo: 1
02Comprueba si dos palabras son anagramas comparando sus frecuencias de letras (usa Counter o dict manual).(media) Amarillo"amor" y "roma" → SÍ son anagramas
03Dada una lista de números con duplicados (hardcoded), devuelve los elementos únicos usando un set.(facil) VerdeÚnicos: {1, 2, 3, 5}
04Pide dos frases al usuario. Muestra las palabras que aparecen en AMBAS frases (intersección de sets).(media) AmarilloPalabras comunes: {'el', 'gato'}
05Two-sum básico: dada una lista de enteros y un objetivo target, encuentra los dos índices cuya suma es target usando un dict.(dificil) Rojo[2, 7, 11, 15], target=9 → [0, 1]
06Agrupa palabras de una frase por su primera letra y muéstralas ordenadas (igual que el worked example pero el usuario introduce la frase).(media) Amarilloa: abeja, aguila / b: ballena
  • Esqueleto de práctica: practica/07-diccionarios-sets/ejNN_practica.py
  • Solución modelo: practica/07-diccionarios-sets/ejNN_modelo.py

Conexiones