Diccionarios complejos (II)
Colecciones de datos
En un diccionario complejo el value (par clave:valor) de un posible "campo" puede estar formado por una lista de datos ([]), de modo que el tratamiento de esos datos haga encesario implementar estrategias específicas. Sin pretender ser exhaustivos, ese tratamiento incluye operaciones como conteo, visualización y consulta (de toda la lista o de un elemento), añadido, supresión o modificación... En esta entrada estudiaremos cómo realizar estas operaciones.
Ya que por algún punto hay que empezar, nos situaremos en el siguiente contexto: hemos definido la estructura de diccionario...
"ALU-cod-n": {
"nombre": "al_nombre",
"curso": "al_curso",
"nee": true,
"medidas_apoyo": [
"mad_1"
],
"intervenciones": [
{
"fecha": "int_aa_mm_dd",
"motivo": "int_mot",
"acuerdos": "int_acuerdos"
}
]
},
... ya sabemos cómo añadir elementos a los "campos" simples nombre - curso - nee...
import json
import os
def solicitar_booleano(mensaje):
"""
Solicita una respuesta booleana al usuario garantizando que la entrada sea s/n.
"""
while True:
respuesta = input(f"{mensaje} (s/n): ").strip().lower()
if respuesta in ['s', 'si', 'sí']:
return True
elif respuesta in ['n', 'no']:
return False
print(" [!] Entrada no válida. Por favor, introduzca 's' para Sí o 'n' para No.")
def capturar_ficha(codigo_num):
cod_alumno = f"ALU-cod-{codigo_num}"
print(f"\n==========================================")
print(f" NUEVA FICHA DE EXPEDIENTE: {cod_alumno}")
print(f"==========================================")
print("\n--- AVISO DE FORMATO DE ENTRADA ---")
print(" * Nombre del alumno: Apellidos, Nombre (ejemplo: García López, María)")
print(" * Curso: Etapa y grupo (ejemplo: 2º ESO B o 1º Bachillerato A)")
print("-------------------------------------\n")
nombre = input("Nombre completo del alumno (ej: García López, María): ").strip()
curso = input("Curso y grupo (ej: 2º ESO B): ").strip()
nee = solicitar_booleano("¿Presenta Necesidades Educativas Especiales (NEE)?")
... pero todavía no sabemos cómo introducir datos en el "campo" "medidas_apoyo": [] cuyo value es una lista, como podemos identificar por el uso corchetes [] como delimitadores. El script que sigue cubre esta necesidad, aunque tiene una funcionalidad limitada.
import json
import os
def solicitar_booleano(mensaje):
"""Solicita una respuesta booleana al usuario garantizando que la entrada sea s/n."""
while True:
respuesta = input(f"{mensaje} (s/n): ").strip().lower()
if respuesta in ["s", "si", "sí"]:
return True
elif respuesta in ["n", "no"]:
return False
print(
" [!] Entrada no válida. Por favor, introduzca 's' para Sí o 'n' para No."
)
# --- FUNCIÓN Cumplimentar datos de medidas_apoyo ---------------------------------------
def capturar_medidas_apoyo():
"""Captura de forma interactiva la lista de medidas de apoyo."""
medidas = []
quiere_anadir = solicitar_booleano(
"¿Desea registrar alguna medida de apoyo?"
)
contador = 1
while quiere_anadir:
medida = input(f" -> Ingrese la medida de apoyo #{contador}: ").strip()
if medida:
medidas.append(medida)
contador += 1
quiere_anadir = solicitar_booleano("¿Desea añadir otra medida de apoyo?")
return medidas
# --- FUNCIÓN PRINCIPAL de ejecución. -----------------------------------------------
def capturar_ficha(codigo_num):
cod_alumno = f"ALU-cod-{codigo_num}"
print(f"\n==========================================")
print(f" NUEVA FICHA DE EXPEDIENTE: {cod_alumno}")
print(f"==========================================")
print("\n--- AVISO DE FORMATO DE ENTRADA ---")
print(
" * Nombre del alumno: Apellidos, Nombre (ejemplo: García López, María)"
)
print(
" * Curso: Etapa y grupo (ejemplo: 2º ESO B o 1º Bachillerato A)"
)
print("-------------------------------------\n")
nombre = input("Nombre completo del alumno (ej: García López, María): ").strip()
curso = input("Curso y grupo (ej: 2º ESO B): ").strip()
nee = solicitar_booleano(
"¿Presenta Necesidades Educativas Especiales (NEE)?"
)
# 1. Llamamos a la nueva utilidad para generar la lista
medidas_apoyo = capturar_medidas_apoyo()
# 2. Retornamos el diccionario completo con el nuevo campo
registro = {
"codigo_alumno": cod_alumno,
"nombre": nombre,
"curso": curso,
"nee": nee,
"medidas_apoyo": medidas_apoyo,
}
return registro
# ==============================================================================
# BLOQUE DE EJECUCIÓN PRINCIPAL
# ==============================================================================
if __name__ == "__main__":
# Solicitamos o asignamos el número identificador para el código de alumno
num_expediente = 1
# Llamada a la función principal para capturar los datos interactivos
expediente_alumno = capturar_ficha(num_expediente)
# Mostramos el resultado por pantalla con formato JSON legible
print("\n==========================================")
print(" REGISTRO GENERADO CON ÉXITO")
print("==========================================")
print(json.dumps(expediente_alumno, indent=4, ensure_ascii=False))
Este script complementa el de creación de registro añadiendo, a partir de def capturar_medidas_apoyo(): le procedimiento para obtener los primeros posibles datos de medidas_apoyo. Esta función es llamada desde la función principal def capturar_ficha(codigo_num): y se basa, en lo fundamental, en el bucle while quiere_anadir: que permite al usuario introducir cuantas medidas de apoyo desee.
Resuelto el procedimiento de creación de datos, nos situamos ahora en el segundo contexto: ya disponemos de un archivo JSON que contiene datos suficientes como para que sea pertinente realizar diferentes operaciones con la información de medidas_apoyo de los distintos registros-diccionarios.
En este contexto empezamos por acceder al archivo JSON para trabajar con él desde el script (en memoria) como diccionario complejo. Este procedimiento ya nos es conocido.
import json
# Ruta absoluta al archivo JSON
ruta_archivo = r"C:\MisDatosPropios\exped_orienta.JSON"
# 1. Cargar el contenido del archivo JSON en memoria
with open(ruta_archivo, "r", encoding="utf-8") as archivo:
expedientes = json.load(archivo)
De las entradas anteriores sabemos crear el listado las claves principales, acceder al contenido de un archivo concreto o a todos ellos. También sabemos manipular el contenido de deteminados campos. Ahora nos detendremos en el acceso y las posibles modificaciones del contenido del campo cuyo value es una lista. Empezaremos por obtener el listado completo de registros mostrando cuántas y cuales son las medidas educativas en cada uno de ellos.
import json
# Ruta absoluta al archivo JSON
ruta_archivo = r"C:\MisDatosPropios\exped_orienta.JSON"
try:
# 1. Cargar el contenido del archivo JSON en memoria
with open(ruta_archivo, "r", encoding="utf-8") as archivo:
expedientes = json.load(archivo)
print("\n==================================================")
print(" LISTADO COMPLETO DE EXPEDIENTES Y MEDIDAS ")
print("==================================================\n")
# Adaptación dinámica según si el JSON es una lista [...] o un diccionario {...}
registros = (
expedientes.items()
if isinstance(expedientes, dict)
else enumerate(expedientes, 1)
)
for id_registro, datos in registros:
# Obtenemos la clave principal (clave del dict o campo 'codigo_alumno')
if isinstance(datos, dict):
clave_principal = datos.get("codigo_alumno", f"Registro #{id_registro}")
medidas = datos.get("medidas_apoyo", [])
else:
clave_principal = str(id_registro)
medidas = datos if isinstance(datos, list) else []
# Contamos la cantidad total de elementos en la lista
total_medidas = len(medidas)
# Imprimimos la salida formateada en CMD
print(f"📌 Clave Principal: {clave_principal}")
print(f" Total de medidas educativas aplicadas: {total_medidas}")
if total_medidas > 0:
print(" Listado de medidas:")
for i, medida in enumerate(medidas, 1):
print(f" {i}. {medida}")
else:
print(" Listado de medidas: (Sin medidas registradas)")
print("-" * 50)
except FileNotFoundError:
print(f" [!] Error: No se encontró el archivo en la ruta '{ruta_archivo}'.")
except json.JSONDecodeError:
print(
" [!] Error: El archivo JSON no tiene un formato válido o está corrupto."
)
Podríamos dirigir nuestra atención al análisis del contenido de este "campo", pero dejaremos estos procedimientos para una tercera fase del estudio de los diccionarios y nos atendremos a explicar los procedimientos de manejo y modificación del value lista, si bien no es muy diferente del del que ya estudiamos en el tratamiento de estas colecciones de datos.
Al tratarse de un diccionario ya desarrollado en cuanto a su contenido, lo primero que deberemos hacer es identificar y acceder al registro de nuestro interés. Para ello debemos usar la clave principal /(vg. "ALU-2024-01") y, a partir de ahí a la clave "medidas_apoyo".
Disponemos de dos procedimientos para acceder a los datos de la lista. Bien directamente identificando al alumno por su clave:
import json
# Ruta absoluta al archivo JSON
ruta_archivo = r"C:\MisDatosPropios\exped_orienta.JSON"
# 1. Cargar el contenido del archivo JSON en memoria
with open(ruta_archivo, "r", encoding="utf-8") as archivo:
expedientes = json.load(archivo)
# 2. Identificamos directamente al alumno por su clave
id_alumno = "ALU-2024-01"
# 3. Verificar existencia y mostrar las medidas elemento por elemento
if id_alumno in expedientes:
print(f"Medidas de apoyo para {id_alumno}:")
for medida in expedientes[id_alumno]["medidas_apoyo"]:
print(f"- {medida}")
... o bien hacerlo de forma interactiva introducciendo por input() el identificador de su clave, suponiendo que tenemos acceso a un listado de claves y nombres que nos facilitan la identificación del sujeto deseado.
import json
# Ruta absoluta al archivo JSON
ruta_archivo = r"C:\MisDatosPropios\exped_orienta.JSON"
# 1. Cargar el contenido del archivo JSON en memoria
with open(ruta_archivo, "r", encoding="utf-8") as archivo:
expedientes = json.load(archivo)
# 2. Listado de claves-sujetos
listado = [f"{clave} - {datos['nombre']}" for clave, datos in expedientes.items()]
for al in listado:
print(al)
# 3. Solicitar la clave directamente al usuario
clave = input("Introduce la clave del expediente: ")
# 4. Acceder al valor del campo 'medidas_apoyo' del registro indicado
medidas = expedientes[clave]["medidas_apoyo"]
# 5. Mostrar el contenido actual
print("Medidas de apoyo actuales:", medidas)
Una vez que accedemos al listado de medidas, podemos limitarnos a mostrarlo, pero también podemos actuar sobre él. Veamos algunas acciones posibles. Se escriben a continuación del script anterior).
print("\n--- ACCIONES SOBRE LAS MEDIDAS ---")
# (1) Conocer el número de medidas
print(f"\n4. Número total de medidas registradas: {len(medidas)}")
# (2) Añadir una nueva medida
nueva = input("1. Introduce la nueva medida a añadir: ").strip()
medidas.append(nueva)
print(" Lista actualizada:", medidas)
# (3) Borrar una medida
a_borrar = input("\n2. Introduce la medida a eliminar: ").strip()
medidas.remove(a_borrar)
print(" Lista tras borrar:", medidas)
# (4) Ordenar alfabéticamente las medidas
medidas.sort()
print("\n3. Medidas ordenadas alfabéticamente:", medidas)
# (5) Saber si existe una determinada medida
buscar = input("\n5. Consulta si existe una medida concreta: ").strip()
print(f" -> ¿Existe '{buscar}' en la lista?: {buscar in medidas}")
Lo suyo sería actualizar el archivo JSON, pero por ahora no es necesario ya que simplmente estamos aprendiendo a trabajar con los componentes del diccionario.
No hay comentarios:
Publicar un comentario
Comenta esta entrada