Nivel: Intermedio
Tema: Diccionarios, listas de diccionarios, agrupación de datos, validación de entradas, tests con pytest
Objetivo: Agrupar elementos de una lista según una clave común, un patrón muy habitual en análisis y transformación de datos.

Enunciado
Crea una función llamada agrupar_por_clave(elementos, clave) que:
- Reciba una lista de diccionarios
elementosy una cadenaclave. - Si
elementosesNone, devuelva un diccionario vacío{}. - Si
elementosno es una lista, lanceTypeError. - Si
claveno es unstr, lanceTypeError. - Devuelva un diccionario donde:
- las claves sean los valores de
claveen cada elemento, - los valores sean listas con los diccionarios que comparten esa clave.
- las claves sean los valores de
- Ignore elementos que no contengan la clave indicada.
Ejemplos
datos = [
{"categoria": "A", "valor": 10},
{"categoria": "B", "valor": 20},
{"categoria": "A", "valor": 15},
]agrupar_por_clave(datos, "categoria")
# {
# "A": [
# {"categoria": "A", "valor": 10},
# {"categoria": "A", "valor": 15}
# ],
# "B": [
# {"categoria": "B", "valor": 20}
# ]
# }
Casos borde:
agrupar_por_clave(None, "categoria")→{}agrupar_por_clave([], "categoria")→{}agrupar_por_clave(datos, "no_existe")→{}
Pistas
- Usa un diccionario para acumular los grupos.
- Recorre la lista elemento por elemento.
- Comprueba si la clave existe antes de agrupar.
- Inicializa la lista del grupo si aún no existe.
Solución explicada (paso a paso)
- Si
elementosesNone, no hay datos → devolvemos{}. - Validamos que
elementossea una lista yclavesea una cadena. - Creamos un diccionario vacío para los grupos.
- Recorremos cada elemento:
- si no es un diccionario o no contiene la clave, lo ignoramos,
- obtenemos el valor asociado a la clave,
- añadimos el elemento al grupo correspondiente.
- Devolvemos el diccionario de grupos.
def agrupar_por_clave(elementos: list | None, clave: str) -> dict: """ Agrupa una lista de diccionarios por una clave común. Reglas: - None -> {} - elementos debe ser list - clave debe ser str - Ignora elementos sin la clave """ if elementos is None: return {} if not isinstance(elementos, list): raise TypeError("El parámetro 'elementos' debe ser una lista o None.") if not isinstance(clave, str): raise TypeError("El parámetro 'clave' debe ser una cadena (str).") grupos = {} for elemento in elementos: if not isinstance(elemento, dict): continue if clave not in elemento: continue valor_clave = elemento[clave] if valor_clave not in grupos: grupos[valor_clave] = [] grupos[valor_clave].append(elemento) return grupos
import pytestfrom reto_13_agrupar_por_clave import agrupar_por_clavedef test_agrupacion_basica(): datos = [ {"categoria": "A", "valor": 10}, {"categoria": "B", "valor": 20}, {"categoria": "A", "valor": 15}, ] resultado = agrupar_por_clave(datos, "categoria") assert resultado["A"] == [ {"categoria": "A", "valor": 10}, {"categoria": "A", "valor": 15}, ] assert resultado["B"] == [ {"categoria": "B", "valor": 20}, ]def test_lista_vacia(): assert agrupar_por_clave([], "categoria") == {}def test_none_devuelve_diccionario_vacio(): assert agrupar_por_clave(None, "categoria") == {}def test_clave_no_existente(): datos = [{"a": 1}, {"b": 2}] assert agrupar_por_clave(datos, "categoria") == {}def test_tipo_incorrecto_elementos(): with pytest.raises(TypeError): agrupar_por_clave("no_es_lista", "categoria")def test_tipo_incorrecto_clave(): with pytest.raises(TypeError): agrupar_por_clave([], 123)
Ejecuta:
pytest -q
Variantes para subir de nivel (opcional)
- Usar
defaultdict(list)para simplificar el código - Agrupar por múltiples claves
- Transformar el resultado (por ejemplo, contar elementos por grupo)
- Soportar claves anidadas (
"usuario.id")
Lo que aprendiste
- Un patrón clave en procesamiento de datos: group by
- Manejo de listas de diccionarios
- Validación defensiva en funciones intermedias
- Tests para estructuras de datos compuestas
Accede al código completo y a los tests en GitHub para ejecutar y modificar la solución localmente.
Continúa con Reto #14 — Eliminar duplicados preservando el orden para seguir trabajando con patrones intermedios de listas y conjuntos.