Capítulo 7: Variables que guardan múltiples valores

Publicado por P. Ruiz en

Arrays

Básicamente, un array es una lista de valores, de cualquier tipo, que podemos identificar de forma individual por la posición que ocupan dentro de la lista. Las posiciones de los diferentes elementos se numeran a partir de cero.

Crear un array

A diferencia de lo que se hace en otros lenguajes de programación, en PowerShell no hay que definir una variable de forma diferente para que actúe como un array. Es suficiente con asignarle un grupo de valores, siguiendo este formato:

PowerShell-UD07-060

Por ejemplo, el siguiente código sería correcto:

PowerShell-UD07-001

Este es, digamos, el formato explícito. Sin embargo, también sería correcto usar expresiones como estas:

PowerShell-UD07-002

o, incluso, usando un rango de valores:

PowerShell-UD07-003

Como hemos dicho más arriba, cada elemento de un array puede ser de un tipo diferente aunque, si necesitamos restringir el tipo de dato que podemos almacenar en ella, basta con indicarlo delante del nombre de la variable. En ese caso, como vamos a almacenar valores enteros, seguiremos el siguiente formato:

PowerShell-UD07-004

No obstante, la misma idea es válida para cualquier otro tipo de dato.

Aunque hemos utilizado el formato estándar, la definición explícita de tipo es válida también con la sintaxis reducida que hemos visto antes:

PowerShell-UD07-005

o también:

PowerShell-UD07-006

Incluso podemos crear un array vacío al que ir añadiendo elementos más tarde:

PowerShell-UD07-007

Mostrar el contenido de un array

Si queremos ver en pantalla el contenido de todo el array en un momento dado, podemos utilizar la misma técnica que con una variable simple:

PowerShell-UD07-008

Y el resultado será como el de la imagen siguiente.

PowerShell-UD07-009

Utilizar un elemento individual del array

Para acceder a un elemento concreto del array, basta con escribir su nombre seguido de la posición que necesitamos, encerrada entre corchetes.

Por ejemplo, para mostrar el primer elemento del array anterior, escribiríamos esto:

PowerShell-UD07-010

Y, como cabe esperar, el resultado será así:

PowerShell-UD07-011

Aunque, si lo que queremos es utilizar el elemento dentro de una expresión, nos limitamos a utilizar la notación anterior como si se tratara de una variable simple.

Por ejemplo, para incrementar en uno el valor del elemento, haríamos esto:

PowerShell-UD07-012

o incluso esto:

PowerShell-UD07-013

En la imagen se ilustra el funcionamiento de ambas expresiones:

PowerShell-UD07-014

Arrays como objetos

Ya dijimos en otro apartado que, internamente, PowerShell trata a todas las variables como objetos. Y, aunque aquí no profundicemos en los conceptos relacionados con la programación orientada a objetos, sí debemos saber que, gracias a esta característica, disponemos de herramientas que nos facilitan la creación, manipulación, búsqueda y ordenación de arrays.

Por ejemplo, si quisiéramos saber cuántos elementos tiene un array, bastaría con escribir lo siguiente:

Scripts-en-PowerShell-Guia-para-principiantes-222

Y, como vemos a continuación, el valor devuelto para el array de ejemplo que hemos venido utilizando, sería 4:

PowerShell-UD07-016

Para conocer en detalle todas las características de la clase Array, puedes recurrir al siguiente enlace: https://msdn.microsoft.com/en-us/library/system.array(v=vs.110).aspx

Recorrer un array

Muchas veces necesitamos realizar operaciones que afecten a todos los elementos de un array. Para estas situaciones podemos utilizar una estructura repetitiva controlada por una variable que actúe como índice del array.

Para entenderlo, quizás lo mejor sea recurrir a un ejemplo; veamos cómo multiplicar por dos cada uno de los valores contenidos en un array:

PowerShell-UD07-017

Observa que la variable $i comienza con el valor cero y, en cada iteración, se incrementa en uno hasta llegar al valor de la última posición del array. Luego, dentro del bloque de código, se utiliza la variable $i para hacer referencia a un elemento particular del array (primero al de la posición 0, luego al de la posición 1, etc.)

En la siguiente imagen puedes comprobar el resultado de ejecutar el ejemplo anterior:

PowerShell-UD07-018

Si necesitáramos recorrer el array en orden inverso, bastaría con modificar los valores de for:

PowerShell-UD07-019

Por supuesto, nos vale cualquier estructura repetitiva, siempre que actúe de forma equivalente a ésta.

No obstante, recuerda que existe una de ellas que está específicamente diseñada para actuar sobre colecciones de datos. Me refiero a la estructura foreach.

Una de las ventajas de usar foreach para recorrer un array es que no necesitamos una variable que vaya tomando el valor de cada posición. Por ejemplo, si queremos resolver la tarea anterior, bastaría con el siguiente código:

PowerShell-UD07-020

De cualquier modo, debemos tener en cuenta una sutil diferencia: mientras en el caso de for estamos accediendo a un elemento del array cada vez, en el caso de foreach se hace una copia de dicho elemento en la variable $elem. Esto significa que, al cambiar el valor de la variable $elem, no estamos cambiando el valor original en el array.

Para comprobarlo, podríamos modificar el ejemplo anterior para que nos vaya mostrando el resultado de cada operación y, al final, el contenido del array:

PowerShell-UD07-021

Observa que, por primera vez, hemos utilizado un argumento en el cmdlet Write-Host. Se trata de -NoNewline, que evita que se produzca un cambio de línea después de ejecutarlo. Así, hemos conseguido que todos los números mostrados en el interior de la estructura foreach aparezcan en la misma línea.

También hemos utilizado un carácter especial (`n) en el último Write-Host. En este caso, la intención era, precisamente, producir un cambio de línea.

La siguiente imagen nos muestra el resultado de la ejecución:

PowerShell-UD07-022

Otro inconveniente de foreach es que siempre recorre todo el array. Si necesitáramos recorrer sólo algunas de sus posiciones, o no quisiéramos hacerlo en el orden preestablecido, quizás sería más recomendable una estructura diferente.

Por ejemplo, imaginemos que tenemos un array que guarda nombres de productos en las posiciones impares y su precio correspondiente en las posiciones pares. Para aplicar un descuento del 10% a todos los productos, la solución más sencilla pasa por no utilizar foreach. Por ejemplo, podríamos aplicar la siguiente solución:

PowerShell-UD07-023

Como PowerShell no tiene en cuenta los saltos de línea ni el exceso de espacios, hemos hecho nuestro código más legible añadiéndolos según nuestro criterio.

Añadir y quitar valores en un array

Cuando necesitamos que un array crezca con nuevos elementos, basta con utilizar el operador de suma (+).

Por ejemplo, podemos crear un array vacío y añadir elementos a medida que los vaya facilitando un usuario:

PowerShell-UD07-024

Su ejecución podría ser como sigue:

PowerShell-UD07-025

También podemos usar el operador de suma para unir dos listas y obtener una tercera:

PowerShell-UD07-026

Cuando comprobamos el resultado obtenemos algo así:

PowerShell-UD07-027

… Incluso podemos añadir una lista a otra:

PowerShell-UD07-028

Y comprobamos que también funciona correctamente:

PowerShell-UD07-029

En ocasiones, la salida de un cmdlet consiste en un array. Esto significa que podríamos asignarla directamente a una variable de este tipo. Un ejemplo puede ser el cmdlet Get-ChildItem que ya conocemos del capítulo anterior.

Get-ChildItem permite obtener la lista de archivos de una o varias rutas del disco

Para comprobar que su salida consiste en un array, bastaría con escribir lo siguiente:

PowerShell-UD07-030

Con el que obtenemos el siguiente resultado:

PowerShell-UD07-031

Como el resultado es satisfactorio, podemos utilizar un array para almacenar la información que nos ofrece escribiendo algo así:

PowerShell-UD07-032

En realidad, Get-ChildItem devuelve un array de objetos donde cada uno representará un archivo del directorio.

A modo de ejemplo, podemos usar la propiedad name de uno de esos objetos, que nos ofrecerá el nombre del archivo correspondiente.

Sabiendo esto, podríamos utilizar una estructura repetitiva que recorra el array y nos muestre los nombres de los archivos contenidos en el directorio. Algo así:

PowerShell-UD07-033

El resultado será así:

PowerShell-UD07-034

En cuanto a la eliminación de elementos de una array, no hay un procedimiento sencillo. Probablemente la mejor solución consista en crear un array nuevo y asignarle únicamente los valores que nos interese mantener.

Por ejemplo, supongamos que, en el array anterior, únicamente queremos mantener los nombres de los archivos que comiencen con la letra ‘D’. Podríamos hacer algo así:

PowerShell-UD07-035

Y si comprobamos el resultado, obtendremos algo como esto:

PowerShell-UD07-036

En realidad, podríamos haber simplificado un poco escribiendo algo así:

PowerShell-UD07-037

Te animo a que lo analices y saques tus conclusiones…

Actividades resueltas: Trata de resolver las siguientes cuestiones, antes de consultar la respuesta:

    1. Crea un script que pida la lista de nombres de una clase. La lista acabará cuando, la persona que la escribe, deje un nombre vacío.

      Cuando hayamos terminado, el programa mostrará en pantalla los nombres que hayamos introducido, pero en orden inverso.

      Nota: Para añadir un nuevo elemento a un array basta con sumárselo. Por ejemplo:

      $var = @(1, 2, 3)
      $var += 4

      Al final, el array tiene los valores 1, 2, 3, 4

      PowerShell-UD07-062

    2. Escribe un script que pida la lista de nombres de una clase. La lista acabará dejando un nombre vacío.

      Cuando hayamos terminado, el programa calculará la longitud media de los nombres (el número total de caracteres introducidos, dividido por el número de nombres).

      Por último, mostrará todos aquellos nombres que tengan un número de caracteres superior a la media.

      Nota: Para saber el número de caracteres de una variable de texto, podemos usar la propiedad Length. Por ejemplo:

      $texto = "Hola"
      Write-Host $texto.Length

      Obtendríamos el valor 4.

      PowerShell-UD07-063

    3. Escribe un script que contenga dos arrays: El primero tendrá los dígitos del sistema de numeración romano y el segundo sus valores. La definición será parecida a esta:

      $dígitos = @("I", "V", "X", "L", "C", "D", "M")
      $valor = @(1, 5, 10, 50, 100, 500, 1000)

      El usuario podrá escribir el carácter de cualquier dígito y el script responderá con su valor. También deberá avisar cuando escribamos un dígito que no exista.

      PowerShell-UD07-064

    4. Partiendo de la idea anterior, escribe un nuevo script que nos pida un valor y nos responda con el dígito correspondiente en el sistema de numeración romano. También avisará cuando no se encuentre el valor aportado.

      PowerShell-UD07-065