DominaDynamo
El contenido de esta obra (texto y vídeos enlazados) está protegido por la Ley de Propiedad Intelectual Española, que establece penas de prisión y/o multas, además de las correspondientes indemnizaciones por daños y perjuicios. No se permite copiar, distribuir, exhibir este trabajo ni realizar otros trabajos derivados del mismo con propósitos comerciales. En caso de citar el trabajo, previa autorización escrita por el propietario del copyright, se deberá reconocer y citar al autor.
©Joan Moretó | DominaDynamo
Dynamo para Revit
Tema 04: Listas
Curso: Dynamo para Revit
Tema 04: Listas
©Joan Moretó | DominaDynamo 2
1. Las listas
Gran parte del potencial de Dynamo reside en su capacidad de trabajar con listas.
Tendremos una lista siempre que un nodo de lugar a dos o más elementos por lo que,
como hemos ido viendo en los temas anteriores, utilizaremos listas en prácticamente
todos los scripts que vamos a desarrollar.
2. Estructura de las listas
2.1. Niveles
Las listas son agrupaciones de elementos que pueden constituir una lista sencilla o
estar agrupadas formando sublistas a distintos niveles.
Vamos a analizar las diferentes estructuras que pueden adoptar las listas mediante un
ejemplo. Tenemos una lista de ciudades:
-En el primer caso todas las ciudades forman una única lista sencilla.
-En el segundo vemos que las ciudades están agrupadas por países, por lo que en
este caso tendremos una lista de listas.
-Por último, en el tercer caso, además de por países, las hemos agrupado por
continentes, creando un nuevo nivel, y tendríamos ya una lista de listas de listas.
Figura 04.01: Estructura de listas
Si hubiera ciudades en distintos planetas, podríamos añadir otro nivel y así
sucesivamente…
Curso: Dynamo para Revit
Tema 04: Listas
©Joan Moretó | DominaDynamo 3
Figura 04.02: Niveles e índices
2.2. Índice
El índice es el número que indica la posición de un elemento en una lista o de una lista
en una lista de un nivel superior.
Puede llamar la atención que el primer índice es el 0 y no el 1 como podría
suponerse. Por tanto una lista de 10 elementos tendrá índices del 0 al 9. Aunque al
principio puede resultar un poco extraño, se trata de algo habitual en programación y
nos acostumbraremos fácilmente.
Como ya iremos viendo, el índice va a ser un elemento fundamental a la hora de
trabajar con listas.
3. Cómo se procesan las listas
Dependiendo de su función, los nodos pueden actuar de dos formas cuando
introducimos una lista en el puerto de entrada.
-Repitiendo la acción que se desarrolla para cada uno de los elementos de la lista.
-Desarrollando la acción a partir de todos los elementos de la lista de manera conjunta.
Lo entenderemos mejor con el ejemplo que se ve en la siguiente imagen.
Curso: Dynamo para Revit
Tema 04: Listas
©Joan Moretó | DominaDynamo 4
Figura 04.03: Procesamiento de listas
En ambos casos partimos de una lista de 5 puntos, pero observamos que, mientras el
nodo Circle.ByCenterPointRadius devuelve un círculo para cada uno de los puntos, el
nodo NurbsCurve.ByPoints devuelve una única curva.
Esto resulta lógico e intuitivo con estos dos nodos: el primero solamente necesitará un
punto para crear cada círculo y el segundo necesita varios puntos para crear una
curva. ¿Pero cómo nos da Dynamo esta información en caso de que no sepamos si el
nodo actúa sobre elementos individuales o sobre listas? Veíamos en el tema 2 que al
pasar el cursor sobre un puerto de entrada aparece el tipo de dato que necesita ese
puerto. Ahora vamos a ver que también nos dirá si necesita un solo elemento o por el
contrario necesita una lista.
.
Figura 04.04a: Nodo círculo
Curso: Dynamo para Revit
Tema 04: Listas
©Joan Moretó | DominaDynamo 5
Figura 4.04b: Nodo curva
Vemos que mientras el nodo correspondiente al círculo (figura 04.04a) policita como
valor de entrada Point el nodo correspondiente a la curva solicita Point[]. Esos
corchetes van a ser los que nos indican que el nodo está pidiendo una lista.
5. Encaje
El encaje es la forma en que se cruzan los datos cuando a los puertos de entrada
llegan distintas listas. Viene representado por el símbolo en la parte inferior derecha
del nodo y existen 3 opciones:
-Más corto (es la posición marcada por defecto): Considerando que al puerto de
entrada 1 llega la lista A (llamaremos a sus elementos a1, a2, a3…) y al puerto de
entrada 2 llega la lista B (llamaremos a sus elementos b1, b2, b3…), el resultado del
nodo sería el correspondiente a combinar a1b1, a2b2, a3b3…hasta el final de la lista
de menos elementos.
Figura 04.05a: Más corto
Curso: Dynamo para Revit
Tema 04: Listas
©Joan Moretó | DominaDynamo 6
-Más largo: Al igual que en el caso anterior, se combinarían los elementos de las dos
listas siguiendo un esquema a1b1, a2b2, a3b3…con la diferencia de que el último
elemento de la lista más corta se repite y se combina con los de la lista más larga
hasta el final de la misma.
Figura 04.05b: Más largo
-Producto vectorial: En este caso se combinan todos los elementos de la lista A con
todos los elementos de la lista B, dando lugar a la creación de nuevas sublistas
provenientes de combinar a1,b1, a1b2, a1b3…, a2b1, a2b2, a2b3…, a3b1, a3b2,
a3b3…
Figura 04.05c: Producto vectorial
Curso: Dynamo para Revit
Tema 04: Listas
©Joan Moretó | DominaDynamo 7
En encaje es una variable muy importante y que con frecuencia vamos a tener que
manipular. Vemos otro ejemplo de su funcionamiento en el siguiente vídeo.
Video 04.01
6. Operar con listas
Gran parte del tiempo que vamos a pasar programando con Dynamo, lo vamos a
dedicar a operar con listas: Seleccionar elementos de la lista, contarlos, filtrarlos,
añadir o quitar elementos (al principio o al final) y muchas más acciones relacionadas
con listas van a formar parte del día a día de nuestro trabajo.
Así que vamos a ver como funcionan algunas de los nodos que usaremos con más
frecuencia a la hora de trabajar con listas. Los encontraremos en 2 sitios: Core>List y
BuiltIn y los hemos clasificado en base a la acción que realizan.
6.1. Creación de Listas
Range / Sequence: Crearán rangos y secuencias de números
respectivamente.
List-Create: Si tenemos elementos aislados, podremos
unirlos creando una lista. Si en cambio unimos listas,
crearemos una lista de listas. Aunque en la mayoría de
los casos si lo serán, no tienen por qué ser de un tipo de
objeto homogéneo (una lista puede incluir puntos, elementos
Curso: Dynamo para Revit
Tema 04: Listas
©Joan Moretó | DominaDynamo 8
de Revit y números, por ejemplo). Podemos pinchar en el + para añadir en la lista
tantos elementos como deseemos.
List.OfRepeatedItem: Repite una lista o un elemento un número de veces dado.
Figura 04.06: OfRepeatedItem
6.2. Consultas o extracción de datos.
Hemos agrupado aquí los nodos que nos darán información sobre las listas o sus
elementos.
Count: Devolverá el número de elementos que hay una lista o el número de
listas que hay en una lista de listas.
Figura 04.07: List.Create y Count
Curso: Dynamo para Revit
Tema 04: Listas
©Joan Moretó | DominaDynamo 9
Vemos en la imagen anterior (Fig. 04.06) como al aplicar en nodo Count a las listas
sencillas nos devuelve el número de elementos que tienen mientras que al aplicárselo
a la lista de listas indica el número de listas que la componen*.
*Más adelante, veremos que también podemos hacer que este nodo nos indique el
número de elementos que componen cada una de las sublistas.
IndexOf / AllIndicesOf: Devuelve el índice de un elemento de la lista.
Si el elemento aparece varias veces, IndexOf nos dará únicamente
el primer índice en el que aparece.
Figura 04.08: IndexOf
ContainsItem: Comprueba si una lista incluye un elemento dado y devuelve
true o false.
AllTrue / AllFalse: Evalúan listas de datos booleanos y devuelven un
único valor true o false en función de que todos los valores sean
verdaderos o falsos.
TrueForAll / TrueForAny: Evalúa el cumplimiento de una condición
dada para el conjunto de una lista y devuelve true si se cumple para
todos los elementos o para alguno respectivamente.
Este nodo utiliza un tipo particular de dato que denominaremos Función
(FunctionObject). Es un concepto un poco complicado pero tendremos que recurrir a él
en ocasiones por lo que hay que prestar atención.
En uno de los puertos de entrada introduciremos una lista y el otro introduciremos una
función o algún tipo de comprobación en relación a esa lista. Lo veremos con el
ejemplo de la imagen.
Curso: Dynamo para Revit
Tema 04: Listas
©Joan Moretó | DominaDynamo 10
Queremos saber si la coordenada X de alguno de los puntos de una lista es menor
que 1. Para ello, utilizaremos el nodo Point.X que extrae la coordenada X de un punto
y lo conectaremos con el puerto de entrada en el que pide una lista (list). La Función
tendremos que introducir por tanto en el puerto de entrada que indica predícate y
consistirá en introducir un nodo, en este caso el nodo < en el que dejamos un puerto
de entrada sin conectar. De este modo, el nodo TrueForAny comprobará si alguno de
los valores que hemos introducido en el puerto list cumple la condición que se evalúa
(en este caso, es menor que 1). Entenderemos mejor el concepto con la práctica y al
ver otros nodos que precisan de una función.
6.3. Seleccionar o filtrar elementos de la lista
Podremos extraer uno o varios de los elementos que componen una lista en base a
distintos criterios.
GetItemAtIndex: Devolverá el elemento o la lista que se encuentra en un
número de índice dado.
Figura 04.09: GetItemAtIndex
First Item / Last Item: Actuarán como el nodo anterior devolviendo el
primer o el último elemento de la lista.
TakeItems: Extraerá un número dado de elementos del principio o del final de
una lista. Para extraer elementos del final, introduciremos en amount un valor
Curso: Dynamo para Revit
Tema 04: Listas
©Joan Moretó | DominaDynamo 11
negativo.
Figura 04.10: TakeItems
FilterByBoolMask: Este nodo, como veíamos con detalle en el tema anterior,
nos servirá habitualmente para filtrar los elementos de una lista que cumplen
una condición dada, aunque estrictamente lo que hace es relacionar 2 listas: una lista
A con elementos de cualquier tipo y otra B con valores booleanos. Devolverá en el
puerto de salida IN los elementos de la lista A que coinciden con valores true de la lista
B y en OUT los que coinciden con valores false.
Figura 04.11: FilterByBoolMask
MaximumItem / MinimumItem: Devolverá el valor más alto o más bajo
de una lista.
6.4. Añadir elementos a una lista
AddItemToEnd / AddItemToFront: Añadirá un elemento al final o al
principio de una lista respectivamente. Atención: Si en vez de un
elemento, añadimos una lista, dará lugar a una estructura poco habitual y en general
desaconsejable en la que uno de los elementos será una lista, como vemos en la
Figura en la que el elemento con índice 5 resulta ser una lista.
Curso: Dynamo para Revit
Tema 04: Listas
©Joan Moretó | DominaDynamo 12
Figura 04.12: Añadir lista al final
List.Join: Si queremos unir dos listas en una sola, podremos utilizar este nodo.
Al contrario de List.Create, que crearía una lista de listas, unirá las listas que
introduzcamos una detrás de otra.
Figura 04.13: List.Join
Insert: Añade un elemento o una lista en un índice dado.
Cycle: Repite una lista (o un elemento) un número determinado de veces
dentro de la misma lista (observad la diferencia respecto al nodo
List.OfRepeatedItem que veíamos antes)
Curso: Dynamo para Revit
Tema 04: Listas
©Joan Moretó | DominaDynamo 13
Figura 04.14: List.Cycle
6.5. Eliminar elementos de una lista
DropItems: Elimina de una lista un número dado de elementos al principio o al
final de la misma. Para que elimine los elementos del final de la lista
introduciremos un número negativo. Utilizaremos con bastante frecuencia este nodo
para eliminar el primer o el último elemento de algunas listas cuando estemos
trabajando con geometría.
Figura 04.15: DropItems
DropEveryNthItem: Elimina de una lista un elemento de cada n a partir de un
desfase dado.
Curso: Dynamo para Revit
Tema 04: Listas
©Joan Moretó | DominaDynamo 14
Figura 04.16: DropEveryNthItem
RemoveItemAtIndex: Elimina un elemento de una lista en el índice
especificado.
UniqueItems: Elimina los elementos repetidos de una lista.
6.6. Cambiar el orden de los elementos
Reverse: Da la vuelta a una lista: el último elemento pasa a ser el primero y el
primero el último. Hay que distinguirlo de otros 2 nodos que se llaman igual
pero se aplican a curvas y a vectores.
Sort: Ordena una lista de acuerdo con su orden “natural integrado”, de acuerdo
con la definición de Dynamo ¿A qué se refiere esto? Si se trata de una lista de
datos numéricos la ordenará en orden ascendente, una lista de datos de texto la
ordenará en orden alfabético y una lista de puntos en función de sus valores X, Y y Z
en ese orden.
Figura 04.17: Sort
Curso: Dynamo para Revit
Tema 04: Listas
©Joan Moretó | DominaDynamo 15
*Si queremos ordenar una lista de números de mayor a menor, podremos utilizar este
nodo y después el nodo Reverse
SortByKey: Ordenará una lista en relación a otra lista en base a sus claves. Es
decir: en el puerto de entrada list introduciremos una lista A de cualquier tipo y
en el puerto keys introduciremos una lista B de la misma longitud y valores numéricos.
El nodo devolverá los elementos de la lista A ordenando los índices con el orden que
se ordenaría la lista B. Usaremos con frecuencia este nodo para ordena listas de
elementos de Revit o de geometría de Dynamo en base a un parámetro numérico de
los mismos. La forma de operar será extraer el dato de la lista inicial y conectar ese
dato al puerto keys.
De esta forma, por ejemplo, podremos ordenar una lista de curvas de Dynamo por su
longitud o una lista de muros de Revit., como vemos en la figura, por su área.
Figura 04.18: SortByKey
Reorder: Reordena una lista en base a sus índices.
ShiftIndices: Desplaza los índices de una lista un número dado de puestos (si,
por ejemplo, como número de puestos introducimos un 2 el elemento que está
en el índice 0 pasará al índice 2, el 1 al 3 y así sucesivamente) Este nodo se usará
frecuentemente cuando deseemos introducir diagonales entre puntos situados en
distintas plantas.
Curso: Dynamo para Revit
Tema 04: Listas
©Joan Moretó | DominaDynamo 16
Figura 04.19: ShiftIndices
6.7. Crear sublistas
Podremos agrupar en listas los elementos de una lista sencilla dando lugar a una lista
de un orden superior.
Chop: Creará sublistas a partir de una lista base con un número de elementos
dado, empezando desde el primer elemento de la lista.
Figura 04.20: List.Chop
GroupByKey: Funciona de forma similar al nodo que veíamos antes
SortByKey. En este caso, en vez de ordenar los elementos de la lista en base
a un parámetro dado, creará sublistas agrupando los elementos que tengan. De este
modo, por ejemplo, podremos agrupar ejemplares de Revit por familia dada o muros
en función del nivel en el que se encuentran.
Curso: Dynamo para Revit
Tema 04: Listas
©Joan Moretó | DominaDynamo 17
Figura 04.21: GroupByKey
7 Listas de listas
Decíamos antes que puede haber listas de un número teóricamente infinito de niveles
(en la práctica no será habitual encontrar listas de más de 3 o 4 niveles).
Esto daría lugar a algunos interrogantes: si, por ejemplo, se utiliza en nodo DropItems
para eliminar el primer elemento de una lista de 2 niveles (una lista de listas) ¿que
eliminará? ¿El primer elemento de cada lista o la primera lista?
En general, por defecto, podemos decir que Dynamo entenderá que se actúa sobre el
elemento de nivel superior, es decir, si tenemos una lista de listas actuará sobre las
listas y si tenemos una lista de listas de listas (3 niveles) actuará sobre las listas de
listas.
Figura 04.22: Listas de listas
Curso: Dynamo para Revit
Tema 04: Listas
©Joan Moretó | DominaDynamo 18
Si queremos intervenir en un nivel inferior deberemos utilizar los modificadores de
nivel. Accederemos a ellos pinchando en la flecha que se encuentra en los puertos de
entrada y marcando la casilla Utilizar niveles. Pinchando en las flechas que nos
aparecen hacia arriba o hacia abajo, podremos seleccionar el nivel en el que
queremos trabajar.
Figura 04.23: Utilizar niveles
Vemos en la imagen inferior como en una lista de listas, al igual que en el caso
anterior, al seleccionar el .elemento situado en el índice nº 1, por defecto se selecciona
la lista situada en ese índice pero utilizando el modificador de nivel podemos hacer
que seleccione cada uno de los elementos situados en ese índice en cada lista.
Figura 04.24: Modificando niveles de entrada
Curso: Dynamo para Revit
Tema 04: Listas
©Joan Moretó | DominaDynamo 19
La casilla Mantener la estructura de las listas servirá para que no se reduzca el
número de niveles al procesar una lista. Esto sucederá en los casos en los que el
puerto de entrada solicite como datos una lista (como veíamos anteriormente que
sucedía con Curve.ByPoints, o como sucede en esta misma figura con
List.GetItemAtIndex. Vemos que, al seleccionar un elemento de cada lista el resultado
es que estos se unen en una única lista. Si queremos que se mantenga como una lista
de listas deberemos activar la casilla y el puerto de entrada aparece marcado en azul.
Figura 04.25: Mantener estructura de listas
En ocasiones, de todos modos, no tendremos tan claro el nivel que debemos utilizar e
incluso, el botón de Mantener estructura de listas puede no funcionar como debería,
de modo que habrá que recurrir al tradicional proceso de prueba y error.
Algunos nodos son específicos para el manejo de listas de listas.
Flatten y List Flatten: El nodo Flatten “aplanará” una lista de listas, es
decir que la convertirá en una lista sencilla independientemente del
número de niveles que tuviera originalmente. List.Flatten, en cambio permitirá
introducir el número de niveles que deseamos aplanar, conservando los restantes (en
listas de 3 o más niveles)
Curso: Dynamo para Revit
Tema 04: Listas
©Joan Moretó | DominaDynamo 20
Figura 04.26: Flatten
Transpose: Entendiendo una lista de listas como una matriz, este nodo permite
intercambiar filas y columnas. Lo veremos mejor en el siguiente ejemplo:
Partimos de una lista de listas de puntos. Al haber creado la lista mediante producto
vectorial, la primera lista estará compuesta por puntos con el primer valor de X y cada
uno de los Y, la segunda con el segundo valor de X… y así sucesivamente.
Curso: Dynamo para Revit
Tema 04: Listas
©Joan Moretó | DominaDynamo 21
Figura 04.28a: Antes de usar List.Transpose
Por lo tanto como vemos en, la imagen, si empleamos el nodo que
PolyCurve.ByPoints, veremos como las líneas unen los puntos de cada columna
(puntos con el mismo valor de X) dando lugar a líneas verticales.
Si aplicamos el nodo Transpose a la lista de listas de puntos, los puntos, en vez de
tener el mismo valor de X, tendrán el mismo valor de Y, lo que da lugar a líneas
horizontales.
Figura 04.28b: Después de usar List.Transpose
Curso: Dynamo para Revit
Tema 04: Listas
©Joan Moretó | DominaDynamo 22
8. Listas vacías y valores nulos.
En ocasiones, algunos nodos darán lugar a listas vacías o valores nulos:
Las listas vacías (empty list) se generarán cuando eliminamos todos los elementos de
una lista.
Figura 04.29: Listas vacías
Los valores nulos (null) aparecerán cuando un nodo de lugar a un resultado inválido
(aunque dentro de la lista si haya otros resultados válidos). Puede darse tanto porque
los elementos que introducimos en los puestos de entrada no son del tipo solicitado
como porque requerimos elementos de un índice inexistente.
Figura 04.30: Valores Nulos
En general, deberemos estar atentos a los nulos y eliminarlos ya que pueden dar lugar
a errores. Por suerte, al ser considerados como errores, cualquier nodo que da lugar a
nulos aparece resaltado en color amarillo con un mensaje del motivo del error (a veces
menos aclaratorio de lo que nos gustaría).
Curso: Dynamo para Revit
Tema 04: Listas
©Joan Moretó | DominaDynamo 23
Hay algunos nodos que trabajan con listas vacías y valores nulos.
Clean: Elimina de una lista, todos los valores nulos y listas vacías. Se puede
elegir si mantener los índices o no (en listas de varios niveles puede tener
sentido mantenerlos, en la mayoría de casos estableceremos la variable en false)
Figura 04.31: List.Clean
IsEmpty / IsNull: Detectan listas vacías y valores nulos respectivamente
y devuelven datos de tipo booleano. Conviene fijarse en la imagen
posterior en que, IsEmpty evalúa listas y, por lo tanto, si queremos evaluar listas de un
nivel inferior tendremos que indicarlo mientras que IsNull evalúa cada uno de los
objetos independientemente del nivel en que se encuentren. Ambos nodos nos podrán
resultar útiles si, en vez de eliminar queremos sustituir este tipo de datos.
Figura 04.31: IsEmpty/ IsNull
Curso: Dynamo para Revit
Tema 04: Listas
©Joan Moretó | DominaDynamo 24
9. Caso práctico
Hemos visto que se puede hacer todo tipo de cosas con las listas, pero ¿para qué
sirve esto? Lo vamos a ver mejor con un ejemplo.
Video 04.02: Trabajar con listas