Pensamiento Computacional · Unidad 4 — Estructuras de datos
Diccionarios
Un diccionario guarda pares clave-valor. En vez de buscar por posición, buscás por nombre — y eso cambia todo.
La explicación
Buscar por nombre, no por número
notas["ana"] → 9
len(notas) → 3
Van con llaves, y cada elemento es clave: valor. La clave hace de índice, y
en vez de ser un número puede ser un texto que significa algo.
Agregar, cambiar, borrar
notas["ana"] = 10 # si existe, la pisa
del notas["luis"] # la borra
Las claves son únicas: no puede haber dos "ana". Asignar sobre una clave existente reemplaza el valor.
La clave que no está
notas.get("pepe") → None, sin error
notas.get("pepe", 0) → 0, el valor por defecto
"pepe" in notas → False
get o preguntá con in antes.
get con valor por defecto es especialmente cómodo para contar cosas.
Recorrer
print(clave, notas[clave])
for clave, valor in notas.items(): # las dos cosas
print(clave, valor)
Ojo: for x in notas recorre las claves, no los valores. Es de lo que más
confunde al principio. Si querés los valores sueltos, notas.values().
Contar cosas: el uso estrella
cuenta = {}
for letra in texto:
cuenta[letra] = cuenta.get(letra, 0) + 1
print(cuenta) # {'c': 1, 'a': 2, 's': 1}
La línea del medio es el idioma que conviene memorizar: "lo que había, o 0 si no había, más
uno". Sin get habría que preguntar con un if cada vez.
Escribir una función que reciba una lista de palabras y devuelva un diccionario con cuántas veces aparece cada una.
El patrón de conteo, que sirve para esto y para mil cosas más:
cuenta = {}
for p in palabras:
cuenta[p] = cuenta.get(p, 0) + 1
return cuenta
Con ["sol", "mar", "sol"]:
"mar" → no estaba: queda en 1
"sol" → ya estaba en 1: queda en 2
resultado: {"sol": 2, "mar": 1}
Por qué get(p, 0) y no cuenta[p]. La primera vez que aparece
una palabra, la clave todavía no existe. Con corchetes eso sería un KeyError y el
programa se cortaría en la primera palabra.
get necesita un if y tres líneas donde había una:
cuenta[p] = cuenta[p] + 1
else:
cuenta[p] = 1
get es la que vas a
ver escrita en todos lados.
Control: la suma de todos los valores del diccionario tiene que dar la cantidad de elementos de la lista original. Acá 2 + 1 = 3 ✓
Escribir una función que reciba un texto y devuelva la palabra más repetida junto con la cantidad de veces que aparece. Si hay empate, tiene que devolver la primera en orden alfabético. Las mayúsculas no cuentan.
El ejercicio tiene tres partes: contar, encontrar el máximo, y resolver el empate. La tercera es la que casi nunca se hace y es la que el enunciado pide explícitamente.
1. Contar, con un diccionario:
for p in texto.lower().split():
cuenta[p] = cuenta.get(p, 0) + 1
cuenta.get(p, 0) es el truco que evita el if: devuelve el valor guardado si la palabra ya está, y 0 si es la primera vez. Sin eso habría que escribir:
cuenta[p] = cuenta[p] + 1
else:
cuenta[p] = 1
El .lower() antes del .split() es lo que hace que "El", "el" y "EL" cuenten como la misma palabra. Y .split() sin argumentos separa por cualquier cantidad de espacios, tabs o saltos de línea, que es lo que se quiere.
2 y 3. El máximo con desempate, en un solo recorrido:
for p in sorted(cuenta):
if mejor is None or cuenta[p] > cuenta[mejor]:
mejor = p
El truco está en recorrer las claves sorted. Como se visitan en orden alfabético y la comparación es > estricta, una palabra empatada nunca desplaza a la que ya está: la primera alfabética se queda. El desempate sale gratis, sin un if aparte.
Si la comparación fuera >=, ganaría la última alfabética, que es lo contrario de lo pedido. Ese solo carácter decide el ejercicio.
La función completa:
cuenta = {}
for p in texto.lower().split():
cuenta[p] = cuenta.get(p, 0) + 1
mejor = None
for p in sorted(cuenta):
if mejor is None or cuenta[p] > cuenta[mejor]:
mejor = p
return (mejor, cuenta[mejor]) if mejor else (None, 0)
Las pruebas:
el:3, gato:2, y:2, perro:1
"a b b a c" → ("a", 2) empate entre a y b
"El el EL perro" → ("el", 3) mayúsculas
"" → (None, 0) texto vacío
El caso del empate es el que hay que probar sí o sí. Con "a b b a c" las dos palabras tienen 2 apariciones, y la respuesta correcta es "a" porque va antes alfabéticamente. Sin el sorted, el diccionario se recorre en el orden en que aparecieron las palabras en el texto, y en un empate ganaría la que apareció primero, que no tiene por qué ser la primera alfabética: con "b a a b c" ganaría "b".
Un control del conteo: la suma de todos los valores del diccionario tiene que dar la cantidad total de palabras del texto. En el primer ejemplo: 3 + 2 + 2 + 1 = 8, y el texto tiene 8 palabras ✓.
Dónde se pierde el punto: usar max(cuenta, key=cuenta.get) y entregarlo. Devuelve una palabra con el máximo, pero en caso de empate devuelve la que apareció primero en el texto, no la primera alfabética — y el enunciado pide una en particular.
Dónde se cae la mayoría
- Acceder con corchetes a una clave que no existe: KeyError y el programa se corta.
- Creer que for x in diccionario recorre los valores. Recorre las claves.
- Esperar que se puedan repetir claves. Asignar sobre una existente la pisa.
Hasta acá la explicación. La práctica es la otra mitad: 8 ejercicios de este tema, en cuatro niveles, que no te dicen sólo si está bien al final sino que te corrigen en cada paso y te explican por qué. Y uno para escribir el programa vos, que se prueba ejecutándolo en Python ahí mismo, en el navegador. Además trae una animación que muestra la idea en movimiento.
Practicar Diccionarios →Dónde entra este tema en el parcial
- Primer parcial — Trazar: for con range y for sobre un diccionario10 puntos · resuelto paso a paso
Los otros temas de la unidad 4
Estructuras de datos