Xojo: Colecciones de datos

Como hemos visto hasta ahora, existen principalmente dos tipos de datos: aquellos como los números enteros, reales o booleanos, por ejemplo, denominados primarios, y los correspondientes a las clases, que o bien pueden ser definidas por nosotros mismos o que son las proporcionadas de serie por el extenso framework de Xojo (incluyendo entre estas los utilizados en la creación de las interfaces gráficas).

También sabemos que para trabajar con los tipos debemos de asignarlos preferiblemente a las variables, pero ¿qué ocurre cuando no podemos anticipar la cantidad de tipos (o variables) con las que tenemos que trabajar? Esto supone un serio problema, dado que no resulta elegante ni práctico declarar de antemano una cantidad ridícula de variables que posteriormente tampoco podemos saber qué relación o tipo de operaciones tendremos que aplicar entre ellas.

Por ejemplo, pensemos en una agenda donde hemos de crear nuevos registros en tiempo de ejecución. De antemano no sabremos cuántos objetos ‘Persona’ tendremos que crear, de modo que desconoceremos cuántas variables hemos de declarar previamente para usarlos. Sería más conveniente disponer de algún tipo que, cual saco, permitiese incluirlos a medida que los vayamos creando para referenciarlos posteriormente.

Es precisamente para este tipo de situaciones donde cobran mayor sentido un tipo de datos muy especiales denominados globalmente como colecciones, y que incluyen los Arrays, Colecciones, Diccionarios y Parejas (Array, Collection, Dictionary y Pair, en la nomenclatura de Xojo).

Dichas clases nos proporcionan las herramientas (métodos) para crear y almacenar una gran cantidad de datos, añadirlos, eliminarlos e incluso realizar algunas operaciones comunes con ellos.

Arrays, todo en orden

Los arrays nos permiten crear listas de datos indizadas y, por tanto ordenadas, a partir del tipo de dato declarado. Su uso es realmente común tanto en Xojo como en otros lenguajes de programación y, en el caso del Xojo, encontraremos multitud de clases con métodos que proporcionan precisamente un array como resultado de la operación.

La declaración de un array no dista mucho del modo en el que lo haríamos para cualquier otro tipo de dato que hayamos visto hasta ahora. Por ejemplo, la siguiente instrucción declararía la variable ‘numeros’ como una variable array que contendrá tipos numéricos enteros:

Dim numeros() as integer

A continuación podremos asignar una lista de valores utilizando la siguiente sintaxis:

numeros = array(1, 3, 6, 4, 2, 5)

O bien mediante el método ‘Append’ (http://docs.xojo.com/index.php/Append) proporcionado por la propia clase Array:

numeros.append = 1

numeros.append = 3

numeros.append = 6

numeros.append = 4

numeros.append = 2

numeros.append = 5

En ambos casos obtendríamos el mismo resultado. Sin embargo con la primera tenemos un código más limpio y resulta más adecuado cuando conocemos de antemano la lista de valores que deseamos incorporar al array, mientras que el método ‘append’ suele utilizarse cuando el dato a añadir en la lista no se conoce de antemano o se produce en tiempo de ejecución (obviamente no como la repetición de líneas que se ha utilizado aquí a modo de ejemplo).

En cualquier momento es posible conocer cuántos elementos contiene nuestra lista utilizando el método ‘ubound‘, donde se indica el índice mayor utilizado por la lista. Por ejemplo:

msgbox str( numeros.ubound() )

Producirá como resultado el número ‘5’. ¿Cómo puede ser esto si la lista contiene seis elementos? La explicación es muy sencilla. Como indicaba al inicio del apartado, los Arrays son listas indizadas y el índice utilizado como base es el número 0; de modo que desde el índice 0 hasta el índice 5 utilizado en nuestro ejemplo hay, efectivamente, un total de seis elementos.

Para acceder a cualquier elemento mediante su índice utilizamos la siguiente sintaxis:

msgbox str( numeros(0) )

msgbox str( numeros(3) )

msgbox str( numeros(5) )

Habrás obtenido los valores ‘1’, ‘4’ y ‘5’, contenidos en cada una de las posiciones indicadas por cada índice.

Al principio puede resultar un poco desconcertante pensar en el índice cero de la lista como en el primer elemento, pero con el tiempo y la práctica te acostumbrarás; y más aun si has trabajado previamente con otros lenguajes de programación puesto que el índice basado en 0 es muy común en la mayoría.

Entonces, teniendo esto en cuenta, ¿qué deberías de hacer en tus programas para presentar una respuesta correcta sobre la cantidad de elementos presentes en un Array? Sencillo:

msgbox str( numeros.ubound() + 1 )

Es decir, sumar uno al valor obtenido mediante el método ‘ubound’ de la clase Array.

Prueba ahora a introducir lo siguiente:

msgbox str( numeros(-1) )

msgbox str( numeros(6) )

 
 

Si todo ha ido bien, tu programa habrá saltado automáticamente a la ventana de depuración mostrando un error de ‘Excepción por un acceso fuera de los límites’; es decir, cuando vayas a acceder a los datos contenidos en tus variables de listado nunca deberás de utilizar un índice negativo (inferior a ‘0’ que es el índice mínimo o base), o bien un valor de índice superior al que puedas obtener mediante el uso del método ‘ubound’.

De hecho, en la práctica es muy común ver esta fórmula para iterar entre los valores de un Array asegurándote así de que no sobrepasas el límite superior:

For n as integer = 0 to numeros.ubound

 msgbox str( numeros(n) )

Next

Otra forma de hacerlo es mediante una versión más avanzada del bucle For… Next como iterador, y donde no es preciso conocer de antemano el índice más alto:

For each elemento as integer in numeros

msgbox str (elemento)

Next

El uso de un modo u otro de iteración entre los elementos del Array vendrá determinado, en cualquier caso, por las necesidades de nuestra aplicación; si bien la segunda es más elegante.

Volviendo al uso de valores negativos como índices de array, el hecho de que no debas de utilizarlos no significa que carezca de utilidad. En concreto, es muy común que compruebes el valor ‘-1’ para asegurarte de que el array devuelto por un método o función no esté vacío y realmente contenga elementos.

Dicho de otro modo, si el método ‘ubound’ de un Array devuelve ‘-1’ significa que dicho array está vacío y no contiene ningún elemento. Veamos un ejemplo:

dim numeros() as integer

if numeros.ubound = -1 then

    msgbox "¡Array vacío!"

else

    msgbox "El array contiene elementos"

end if

Definir el tamaño de un Array

Hasta ahora hemos visto el uso más flexible en la declaración de los Array, donde no se ha indicado ningún tipo de limitación sobre la cantidad de datos que pueda contener. Sin embargo, en determinado tipo de aplicaciones sí es preciso trabajar con variables array con una capacidad preestablecida. En dichos casos la declaración de las variables sería del siguiente modo:

Dim numeros(9) as integer

¿Cuántos elementos podrá contener este array? Probemos:

For n as integer = 0 to 9

    numeros(n) =  n + 1

next

msgbox str( numeros(9) )

Recuerda, ¡de 0 a 9 hay 10 elementos!

Por supuesto, también puede presentarse el caso que durante la ejecución de nuestra aplicación debamos de modificar la capacidad previamente establecida para un array.

El modo más romper la barrera previamente establecida sería utilizando el método ‘append’ que ya hemos visto anteriormente y mediante el cual simplemente estaríamos añadiendo un nuevo elemento al final de la lista en cuestión.

Sin embargo, en otros casos deseamos utilizar un nuevo límite conocido de elementos. En esta situación estaríamos hablando de que hemos de redimensionar el array, utilizando para ello la palabra clave ReDim:

Redim numeros(19)

msgbox str( numeros(18 )

 
 

Como puedes ver en la imagen, cuando se redimensiona una variable de array utilizando una capacidad superior a la original conservaremos los datos almacenados originalmente por dicho array, al tiempo que las nuevas posiciones se completan con el elemento por defecto del tipo: ‘0’ en el caso de los enteros, ‘False’ si es booleano, y ‘Nil’ si se trata de un array de objetos, por ejemplo.

Pero igual que utilizamos Redim para aumentar la capacidad de nuestras variables de array, también es posible emplearlo para reducir su tamaño:

Redim numeros(5)

Como cabe esperar, en este caso el array perderá todos aquellos elementos que estuviese almacenando por encima del nuevo índice utilizado como máximo.

Por último, mediante la siguiente sintaxis estaríamos vaciando por completo los contenidos de un array y, de hecho, supone el mejor modo de hacerlo:

Redim numeros(-1)

¡Recuerda: '-1' = Array vacío!

Asignación entre arrays

Algo con lo que debes de guardar especial cuidado es con la asignación entre variables de array, dado que para este tipo de variables rigen las mismas normas que hemos ido viendo hasta ahora.

Teniendo en cuenta todo lo que sabemos sobre el comportamiento de las variables hasta ahora, ¿qué resultado será el mostrado por la ventana modal en este ejemplo?:

Dim numeros(9) as integer

for n as integer = 0 to 9 

 numeros(n) = n + 1

  next

  dim otrosNumeros() as integer

  otrosNumeros = numeros

  otrosNumeros(9) = -1

  MsgBox str( numeros(9) )

Antes de que contestes, te sugiero que refresques tu memoria releyendo la parte final de la anterior entrega sobre pasar datos por valor o por referencia; después de todo, ¡los Array son objetos!

Efectivamente, el valor guardado en ‘numeros(9)’ será el de -1 modificado en la línea ‘otrosNumeros(9)’. ¿Cómo puede ser esto si se tratan de dos variables distintas? El secreto está en la asignación: ‘otrosNumeros = numeros’.

Si fuesen tipos de datos primitivos, Xojo establecería una nueva copia del valor almacenado en ‘numeros’ para la nueva variable ‘otrosNumeros’, pero como ambas son variables de un objeto Array… en ambos casos se apunta (por referencia) al mismo conjunto de datos.

Es decir, si una variable modifica cualquiera de los valores de la lista, la otra variable también reflejará los cambios producidos.

Debes de tener en cuenta siempre este principio cuando trabajes con Arrays, dado que suele ser fuente de una buena cantidad de problemas, al pensar erróneamente que los datos quedan ‘congelados’ simplemente por el hecho de haber asignado un array existente sobre otra variable distinta.

Tal y como se comentó en la anterior entrega, por supuesto este principio también es válido cuando pasamos el array como parámetro de un método. En este caso, la signatura del método se hará siguiendo el mismo principio que en la definición de las variables, tal y como se puede ver en la captura, donde el parámetro ‘p’ está declarado como un array de tipo entero.

Próxima parada: Collections

En la próxima entrega veremos otro par de clases dedicadas al almacenamiento de colecciones: Collection y Dictionary. Hasta entonces, practica con los Array y, especialmente, con los métodos que no hemos visto aquí: insertar, averiguar el índice de un elemento, ordenar… e incluso crear y trabajar con Arrays multidimensionales (con dos o más índices, denominados matrices).

Enlaces de Interés sobre Xojo

Artículos anteriores

Javier Rodríguez (@bloguintosh) es desarrollador OS X e iOS, director de Macsoluciones.com. Puedes contactar con él para el desarrollo de aplicaciones para Mac e iOS en entornos empresariales así como consultoría y formación.

Javier Rodríguez

Javier Rodríguez (@bloguintosh) es desarrollador y autor del eBook "Programación Multiplataforma Xojo". Puedes contactar con él para el desarrollo de aplicaciones y soluciones multiplataforma, así como consultoría y formación en www.aprendexojo.com

0 0 votos
Article Rating
Subscribe
Notify of
0 Comments
Opiniones Inline
Ver todos los comentarios
0
Me encantaría saber tu opinión, por favor, deja un comentariox
()
x