Ilustración conceptual de puertas ordenadas en dos soportes que conservan sus etiquetas de identidad.

Listas y arrays: trabajar con muchos elementos a la vez

Cuatro puertas, cuatro variables: puerta1, puerta2, puerta3 y puerta4. La quinta ya está solicitando una ampliación del organigrama. Podríamos seguir poniendo nombres hasta llenar la pantalla, pero me han reservado este artículo para explicar una alternativa bastante menos ceremonial: guardar varios valores en una colección y trabajar con ella como un conjunto organizado de entradas.

Utilizaremos cuatro identificadores ficticios de puertas para entender qué conserva una secuencia: sus elementos, su orden y su longitud. Después cambiaremos ese orden y comprobaremos qué sigue significando cada posición. La lista de Python, el array de C# y List<T> permiten resolver partes de este problema, aunque tienen diferencias que importan al añadir elementos o preparar una copia. No consultaremos un modelo; vamos a dejar preparada la colección que recorreremos en el siguiente artículo.

Tabla de contenidos

Una colección pone un límite a las variables numeradas

Una secuencia reúne valores bajo un mismo nombre y permite consultarlos por su posición. En Python podemos escribir una lista con corchetes y separar sus elementos con comas. El nombre puertas identifica la colección completa; cada texto del interior representa uno de los identificadores de nuestro ejercicio. La colección no sabe qué es una puerta, ni comprueba que exista en Revit. Esa interpretación forma parte del acuerdo sobre los datos que le hemos entregado.

Guardar cuatro identificadores juntos permite preguntar cuántos hay, consultar uno o entregar la lista completa a otra operación. Con cuatro variables independientes habría que mantener también el conocimiento de cuántas existen y cómo se llaman. Añadir una puerta obligaría a cambiar el programa en varios lugares. La colección concentra esa variación en los datos, que es un sitio mucho más razonable para guardar la cantidad de puertas que una sucesión de nombres inventados con entusiasmo.

Este primer fragmento se puede guardar en un archivo .py y ejecutar con Python 3.12. Muestra la longitud, el primer identificador y el último. Los valores están deliberadamente desordenados para que después podamos distinguir la posición de la identidad.

				
					puertas = ["P03", "P01", "P04", "P02"]
print(len(puertas))
print(puertas[0])
print(puertas[-1])
				
			

La salida es 4, P03 y P02, en líneas separadas. len devuelve la cantidad de elementos. El índice 0 consulta la primera posición; en Python, -1 consulta la última. La última posición también puede expresarse como la longitud menos uno, siempre que exista algún elemento. Cuatro valores ocupan las posiciones cero, uno, dos y tres: contar elementos y numerar posiciones son dos operaciones distintas.

Una lista puede contener valores repetidos y Python admite mezclar tipos. Que lo permita no convierte cualquier mezcla en una buena entrada para tu herramienta. Si el contrato dice «identificadores de puertas como texto», introducir además una altura y un mensaje de error obliga a quien reciba la lista a adivinar qué ha llegado. Yo conservaría un significado reconocible por colección. La flexibilidad del lenguaje ya hará suficientes demostraciones sin que organicemos otra.

El índice localiza una posición, no acredita una identidad

puertas[0] devuelve ahora P03 porque ese valor ocupa la primera posición. Si ordenamos la colección, esa misma consulta podrá devolver P01. La puerta representada por P03 no ha cambiado de identidad: ha cambiado de lugar dentro de nuestra secuencia. Esta distinción parece pequeña hasta que una automatización utiliza el número de fila de Excel para decidir a qué elemento del modelo le escribe un valor.

En un recorrido controlado, trabajar por posición puede ser perfectamente válido. El problema es suponer que dos colecciones independientes mantienen siempre la misma correspondencia porque hoy aparecen alineadas. Una ordenación, una fila eliminada o una consulta con otro orden rompe esa suposición. La longitud tampoco la repara: dos listas de cuatro elementos pueden relacionar cuatro parejas equivocadas con una simetría admirable.

Todavía no vamos a construir una unión por clave; tendrá su propia explicación. Basta con conservar aquí una decisión: el índice expresa una posición dentro de esta colección concreta. Si necesitamos identificar una puerta después de ordenar o filtrar, debemos conservar el identificador y entender su ámbito. Nuestros textos P01 y P02 son datos ficticios, no una garantía de unicidad entre proyectos, documentos o exportaciones reales.

Los límites del índice también son concretos. En la lista inicial, consultar la posición 4 provoca IndexError, porque esa quinta posición no existe. El error no dice que la puerta sea inválida; dice que la consulta queda fuera de la secuencia. Son diagnósticos diferentes y necesitan respuestas diferentes. Repetir la misma consulta con más confianza no crea la casilla que falta, por mucho que esa estrategia tenga una larga tradición informática.

Añadir, ordenar y copiar cambian cosas distintas

La lista de Python puede crecer mediante append, que añade un elemento al final. También podemos ordenar sus textos. En este ejercicio utilizaremos sorted para obtener otra lista ordenada, conservando la original. La documentación de listas de Python distingue esas operaciones y también sort, que modifica la lista existente. Elegir entre ambas afecta a lo que verán otras partes del programa.

				
					puertas = ["P03", "P01", "P04", "P02"]
vista_ordenada = sorted(puertas)
puertas.append("P05")

print(", ".join(puertas))
print(", ".join(vista_ordenada))
				
			

La primera línea muestra P03, P01, P04, P02, P05; la segunda, P01, P02, P03, P04. La vista ordenada se creó antes de añadir P05, y es otra lista. Aquí el nombre «vista» describe su finalidad para el lector; no significa que esté conectada automáticamente con la primera colección. Si necesitas mostrar datos actualizados, tendrás que volver a construirla o elegir otro diseño que mantenga esa relación.

Hay una confusión más sutil: asignar una lista a otro nombre no crea por sí solo una copia. Ambos nombres pueden referirse al mismo objeto. El siguiente fragmento hace visible esa diferencia con una modificación pequeña. copy crea una copia superficial; para estos identificadores, que son textos, basta para separar las listas. Con objetos que contienen otros objetos habría que estudiar qué referencias siguen compartidas.

				
					puertas = ["P03", "P01", "P04", "P02"]
alias = puertas
copia = puertas.copy()
alias.append("P05")

print(len(puertas))
print(len(copia))
				
			

Obtendrás 5 y 4. El nombre alias ha permitido modificar la misma lista que consulta puertas; copia conserva cuatro posiciones. Cambiar el nombre de una referencia no independiza los datos. Yo haría esta prueba antes de llamar «original» a una colección que cualquier paso posterior puede modificar. Es una etiqueta bastante solemne para algo que quizá siga compartiendo la misma memoria con su presunta copia de seguridad.

En C# conviene elegir si la longitud debe cambiar

Un array de C# guarda elementos de un tipo declarado y su longitud queda fijada al crear esa instancia. Podemos reemplazar el valor de una posición válida, pero añadir una nueva posición exige otra estrategia, como crear un array distinto. List<T> ofrece una colección cuyo número de elementos puede crecer o reducirse mediante sus operaciones. La letra T representa el tipo de los elementos; List<string> contiene textos.

Este programa completo para una consola de .NET 8 consulta el mismo conjunto de cuatro identificadores. Después crea una lista a partir del array y le añade P05. Utiliza una sintaxis de inicialización tradicional para que la explicación se centre en las colecciones, sin depender de abreviaturas nuevas del lenguaje.

				
					using System;
using System.Collections.Generic;

string[] puertas = { "P03", "P01", "P04", "P02" };
Console.WriteLine(puertas.Length);
Console.WriteLine(puertas[0]);
Console.WriteLine(puertas[puertas.Length - 1]);

var seleccion = new List<string>(puertas);
seleccion.Add("P05");
Console.WriteLine(seleccion.Count);
Console.WriteLine(puertas.Length);
				
			

Las salidas son 4, P03, P02, 5 y 4. El array conserva su longitud mientras la lista incorpora un quinto elemento. La propiedad Length corresponde al array; Count, a la lista. No estamos demostrando que una estructura sea mejor para cualquier tarea: estamos eligiendo una que permita expresar si el número de entradas debe cambiar. La referencia de arrays de C# documenta la longitud fija de la instancia y el acceso desde cero.

En estas estructuras de C#, escribir puertas[-1] no reproduce la consulta final de Python. Para no mezclar convenciones, hemos utilizado Length - 1. También existen otras formas de acceso en C#, pero copiarlas sin explicar su sintaxis solo cambiaría un fundamento por dos abreviaturas. La equivalencia que interesa aquí es el resultado: localizar el último elemento de una colección que sabemos que no está vacía.

Igual que en Python, asignar un array o una lista a otro nombre no los copia automáticamente. Para los textos de este ejemplo, construir new List<string>(puertas) crea una colección separada con los mismos valores. Si después trabajamos con referencias a objetos del modelo, copiar la colección no duplicará esos elementos en Revit. Separar el recipiente y duplicar lo que representa cada entrada son trabajos diferentes.

Una selección vacía también tiene un resultado válido

Una búsqueda puede devolver cero puertas. Eso no demuestra por sí solo que haya fallado: quizá ninguna cumpla el filtro. La colección vacía permite representar ese resultado, pero no tiene una primera posición que consultar. Antes de mostrar el primer elemento debemos comprobar la cantidad. En Python podemos expresarlo con el condicional que ya vimos, sin utilizar una excepción como parte del recorrido habitual.

				
					puertas = []
if len(puertas) > 0:
    print(puertas[0])
else:
    print("No hay puertas en la seleccion")
				
			

En C# la misma decisión se puede escribir sobre un array vacío. El programa siguiente es independiente del anterior y también funciona en una consola de .NET 8. La condición protege el acceso: cuando la longitud es cero, el programa solo ejecuta el mensaje alternativo.

				
					using System;

string[] puertas = Array.Empty<string>();
if (puertas.Length > 0)
{
    Console.WriteLine(puertas[0]);
}
else
{
    Console.WriteLine("No hay puertas en la seleccion");
}
				
			

Ambos ejemplos imprimen No hay puertas en la seleccion. Para una posición recibida de otra parte del programa no bastaría con comprobar que hay elementos: también habría que validar que el índice concreto está dentro de su rango. En Python existen índices negativos válidos; en nuestros arrays y listas de C# usaremos posiciones enteras desde cero. Aplicar el mismo control sin mirar el lenguaje puede rechazar una consulta válida o aceptar otra que acabará fallando.

Ya podemos entregar una colección completa a un recorrido sin inventar una variable para cada puerta. Antes de avanzar, añade P05 a una lista, ordénala y comprueba qué devuelve la primera posición. Después repite la consulta con una selección vacía. Si conservas la diferencia entre posición, identificador y cantidad, el siguiente bucle tendrá datos razonables que recorrer. Parece una exigencia modesta, pero muchas automatizaciones prefieren reservar esa conversación para después de escribir los valores en el sitio equivocado.

Artículos relacionados

Respuestas

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *