Fundamentos

Estructuras de control FOR y FOREACH

Básicos Definiciones Fundamentos

Cuando vimos la estructura de control WHILE, pusimos como ejemplo un programa que calculaba el valor de la suma de los 1000 primeros números recorriéndolos todos ellos. Sin embargo, se puede hacer mejor y, para ello, existen las estructuras de control FOR y FOREACH.

Estas estructuras de control FOR y FOREACH podríamos traducirlos como PARA y PARA CADA. Enseguida veremos su significado.

Cuando el rango de elementos es conocido

En el caso del ejemplo citado, conocíamos el rango de los elementos que necesitábamos. Es decir, sabíamos el total de números que, en ese caso era de 1000. Para recordarlo, vamos a volver a copiar aquel pseudocódigo.

sumatorio = 0
incremento = 1
WHILE (incremento <= 1000) {
  sumatorio += incremento
  incremento += 1
}
IMPRIMIR sumatorio

Inicialmente, debemos definir el valor de la variable incremento. A continuación, cada iteración del bucle WHILE hace la comparación de si incremento es menor o igual a 1000. Finalmente, dentro de las instrucciones que se repiten debemos sumar uno a nuestra variable incremento para llegar hasta el final.

¿Pero podríamos hacer todas estas cosas en un sólo paso? Sí, y para ello existe la estructura de control FOR.

Estructura de control FOR

El bucle FOR va a realizar la definición, comparación y variabilidad en una sola línea. Vamos a ver a continuación cómo quedaría el mismo programa cambiando la sentencia WHILE por la sentencia FOR.

sumatorio = 0
FOR (incremento = 1; incremento <= 1000; incremento += 1) {
  sumatorio += incremento
}
IMPRIMIR sumatorio

Analicemos la sintaxis de esta nuestra estructura. Inicialmente, nos llama la atención el haber colocado esos puntos y coma dentro del paréntesis del FOR. Aunque estemos en pseudocódigo, estamos utilizando nomenclaturas y formas más o menos comunes a todos los lenguajes de programación, así que estos puntos y coma lo que hacen es separar las tres “definiciones”, por decirlo de alguna manera, del FOR.

En la primera parte, y como se puede deducir, tenemos la asignación inicial de la variable incremento. A continuación tenemos la condición y, para terminar, tenemos cómo debe cambiar esa variable. Se leería algo así como “para incremento que empieza valiendo 1, mientras incremento sea menor o igual a 1000 y aumentando incremento en una unidad en cada paso haz lo siguiente”.

Por tanto, la única instrucción dentro del bucle FOR, la de ir sumando el valor de incremento y guardándolo en sumatorio, se va ejecutando una, dos, tres, cuatro…, hasta llegar al momento en que incremento pasa a valer 1001 y ya no se cumple la condición.

Nota
Imaginamos que podrás pensar que puedes jugar con estos valores a tu voluntad. Es decir, podrías contar el sumatorio de los números pares hasta el 1000 haciendo que la variable se incrementara en dos unidades y su valor inicial fuera un 2. O puedes incluso realizarlo al revés, es decir, que el valor inicial fuera 1000, la condición fuera mientras es mayor o igual a 0 y se fuera decrementando de uno en uno. Posibilidades hay las que puedas imaginar para recorrer cosas.

También puedes modificar la variable incremento dentro del propio bucle. Sin embargo, piensa que ésto afectará al número de veces que se recorrerá el bucle.

Jugando con las condiciones

Un pequeño inciso. ¿Tenemos todos claro que estas tres construcciones hacen lo mismo?

FOR (incremento = 0; incremento < 5; incremento += 1) {
  IMPRIMIR 'Hola'
}

FOR (incremento = 1; incremento <= 5; incremento += 1) {
  IMPRIMIR 'Hola'
}

FOR (incremento = 1; incremento < 6; incremento += 1) {
  IMPRIMIR 'Hola'
}

En los tres casos, se imprimirá cinco veces ‘Hola’. El primer caso difiere un poco, pues nuestra variable incremento toma los valores 0, 1, 2, 3 y 4. Pero en el segundo y tercer caso, la variable toma los valores 1, 2, 3, 4 y 5, pues es lo mismo menor o igual a 5 que menor que 6. Al no imprimir ni necesitar la variable incremento nada más que para repetir el número de ejecuciones, las tres construcciones hacen lo mismo.

Sin embargo, en programación la más utilizada y aconsejada es la primera opción. Veremos por qué a continuación.

Utilizando arrays

Como vimos en el artículo anterior, los arrays son colecciones de elementos a los que podemos acceder a partir de un índice. Es decir, encajan como un guante para nuestras estructuras de control FOR y FOREACH, como veremos luego en este último caso.

Supongamos que tenemos, en un array, los gastos diarios realizados durante una semana. Y nos gustaría saber cuánto hemos gastado en total en esa semana. Lo lógico que haríamos todos sería coger e ir sumando uno a uno los gastos diarios para obtener el gasto de la semana. ¿Podemos expresarlo con nuestro bucle FOR? Allá vamos:

gastos = [28.95, 56.45, 12.85, 20.0, 0.0, 85.99, 32.75]

suma_de_gastos = 0.0
FOR (indice = 0; indice < 7; indice += 1) {
  suma_de_gastos += valor_del_día_indice_en_el_array_gastos
}

IMPRIMIR suma_de_gastos

Como aún no hemos visto bien cómo trabajar con arrays, lo cual veremos en el próximo artículo, vamos a dejarlo indicarlo de esa forma. Inicialmente definimos nuestro array de gastos diarios, con siete gastos que corresponden a cada día de la semana. A continuación iniciamos la variable que contendrá la suma a 0. Posteriormente definimos nuestro bucle FOR, que comenzará valiendo 0 y llegará hasta 6 yendo de uno en uno y ejecutando así 7 veces (0, 1, 2, 3, 4, 5 y 6) la instrucción de suma.

La instrucción dentro del FOR accederá al valor de cada día (ya veremos cómo en el próximo artículo) y lo sumará a lo que ya había. Por tanto, al final tendremos la suma de gastos de toda la semana. Nuestro bucle FOR es perfecto, por tanto, para recorrer los arrays.

Nota
En este caso sabíamos perfectamente que el array contenía 7 elementos. Sin embargo, la mayoría de veces no sabremos cuántos elementos hay. Para ello, utilizaremos métodos para que el propio programa cuente primero cuántos elementos hay en el array y así recorrerlos sin problema.

Problema con arrays con índices no numéricos

Nuestros arrays pueden tener índices no numéricos como vimos en su definición (aunque no en todos los lenguajes de programación). Ésto nos puede ser muy útil pero también nos puede generar muchos problemas. Vamos a coger el ejemplo de los gastos diarios y modificarlo un poco de la siguiente manera:

gastos = [
  'lunes' => 28.95,
  'martes' => 56.45,
  'miercoles' => 12.85,
  'jueves' => 20.0,
  'viernes' => 0.0,
  'sabado' => 85.99,
  'domingo' => 32.75
]

suma_de_gastos = 0.0
FOR (indice = 0; indice < 7; indice += 1) {
  suma_de_gastos += valor_del_día_indice_en_el_array_gastos // ¡¡Da error!!
}

IMPRIMIR suma_de_gastos

Como hemos indicado en el ejemplo, la línea que suma los gastos daría error. ¿Por qué? Porque indice está cogiendo los valores 0, 1, 2, 3, 4, 5 y 6 pero, sin embargo, ahora nuestro array tiene de índices los valores ‘lunes’, ‘martes’, ‘miercoles’, ‘jueves’, ‘viernes’, ‘sabado’ y ‘domingo’. Por tanto, cuando intentamos acceder a valor 0 del índice (o al 1, al 2, etc.), el programa fallaría porque no encuentra ese índice en el array y nos devolvería un error.

Para solucionar este problema existe el bucle FOREACH.

Estructura de control FOREACH

Las estructuras de control FOR y FOREACH se complementan de forma que la primera se suele usar cuando el índice es numérico y la segunda cuando no sabemos qué índice tiene nuestro array. Realmente, podríamos decir que en los lenguajes donde se pueden colocar índices no numéricos, la estructura FOREACH es prácticamente utilizada siempre en detrimento del FOR. Sin embargo, en lenguajes de programación donde no se pueden colocar índices no numéricos, directamente la estructura FOREACH no existe y sólo se utiliza FOR.

Por tanto, utilizaremos FOREACH para recorrer un array de principio a fin sin preocuparnos por los índices (aunque ya veremos que podemos utilizar estos índices a nuestro favor). Se podría decir que este bucle hace que “para cada uno de los elementos haz…”, por lo que recorre del primero al último. En consecuencia, vamos a reescribir el pseudocódigo anterior para evitar el error.

gastos = [
  'lunes' => 28.95,
  'martes' => 56.45,
  'miercoles' => 12.85,
  'jueves' => 20.0,
  'viernes' => 0.0,
  'sabado' => 85.99,
  'domingo' => 32.75
]

suma_de_gastos = 0.0
FOREACH (gastos AS gasto_diario) {
  suma_de_gastos += gasto_diario
}

IMPRIMIR suma_de_gastos

Veamos las líneas 12 y 13, que son las que hemos modificado. Aquí tenemos a nuestro FOREACH cuya definición suele llevar, en la mayoría de lenguajes, un segundo término como hemos colocado aquí AS (traduciríamos por COMO). Podríamos leerlo como “para cada uno de los elementos que hay en la variable gastos como gasto_diario, haz…”. Es decir, que la variable gasto_diario cogerá, en cada iteración del bucle, los elementos que hay en gastos, uno a uno.

De esta forma, en la primera iteración nos encontraríamos con que gasto_diario es 28.95 (es decir, el gasto del lunes), en la segunda iteración gasto_diario es 56.45 (el gasto del martes) y así hasta llegar al final, en el que el bucle se detiene automáticamente. Así pues, nuestra estructura FOREACH es tremendamente útil.

Posteriormente, cuando entremos más a fondo en ver su uso en PHP, veremos que también podemos acceder al índice. De esta forma, podríamos imprimir por pantalla, por ejemplo, el día y el gasto que hemos realizado cada día.

Resumen

Hemos visto en este artículo las estructuras de control FOR y FOREACH, las cuales nos van a permitir recorrer una serie determinada de elementos o también recorrer los elementos de un array. También hemos visto la potencia de FOREACH en general y en particular cuando nuestros índices no son numéricos. Con esto, nuestras estructuras de control principales quedan definidas.

En el próximo artículo veremos cómo trabajar con arrays en PHP para, en el siguiente, empezar a utilizar estas nuevas estructuras con ejemplos reales.

Deja un comentario