Curso de PHP: Nivel Básico – Clase 8. Arrays multidimensionales

Hemos llegado a la Clase 8 del Curso de PHP Básico. Esta clase puede tomarse como una continuación de la clase 3: Introducción a los Arrays puesto que los temas están íntimamente relacionados. Bien podría haber introducido esta parte en aquella clase, pero por razones de extensión decidí separarlo y dejarlo para más adelante.

Esta clase 8 tratará sobre los arrays multidimensionales, es decir, arrays dentro de arrays. Luego de la teoría, hay unos ejercicios muy interesantes para encarar. Tengan en cuenta que a medida que avanzan las clases y se presentan nuevas herramientas, estas son necesarias en varias oportunidades para resolver las prácticas.

A lo largo de este artículo se presentan ejemplos. El código fuente para seguirlos se encuentra aquí y la salida de ese código, aquí.

Aclaración previa sobre los arrays en PHP

Cuando se estudian lenguajes de programación en el ámbito universitario o en cualquier curso de programación que no sea web, se presentan los distintos tipos de datos y entre ellos aparecen los denominados arrays, que ya hemos visto. Debemos tener en cuenta que en PHP, estos tipos de datos no son exactamente iguales a los de lenguajes como Pascal, C, Java y otros. En PHP, los arrays son estructuras más complejas que reciben el nombre de mapas, un tipo de dato más general que el array. Estos mapas pueden usarse como arrays, aunque también como pilas, listas y colas (lo veremos en una clase más adelante).

Aunque lo que hayamos estado usando en realidad no sea lo que parece ser (o sea algo mucho mayor) no nos cambia nada. Cuando los usamos como arrays sabemos cómo se comportan y cómo obtener provecho de ellos.

En esta clase vamos a usar los arrays multidimensionales con la misma limitación de otros lenguajes. Es por eso que vamos a ver tablas donde la cantidad de columnas y de filas son iguales para todos los elementos que están dentro. No debemos perder de vista, también, que una de las principales utilizaciones de PHP es para procesar los resultados devueltos por consultas a bases de datos, que suelen ser estructuras del tipo de tablas.

Arrays multidimensionales

Un array multidimensional es básicamente un array en cuyo interior tiene otro array. Este, a su vez, puede tener otro y así sucesivamente. Se denomina dimensión al nivel de anidamiento o de inclusión de arrays que se alcanza. Por ejemplo, un array multidimensional de dimensión 2 está compuesto de un array que dentro tiene otros arrays y estos últimos no tienen más arrays dentro.

En otras palabras, un array multidimensional de dimensión 2 equivale a una tabla como puede ser la típica planilla de cálculo de Excel, una lista de los empleados de una empresa con información acerca de cada uno, la tabla de posiciones de un campeonato de fútbol o cualquier otra tabla de datos que se imaginen.

Un array multidimensional de dimensión 3 es algo un poco más difícil de encontrar, pero puede darse el caso. Se suelen ver como una pila de tablas. Es decir, como si pusiéramos una tabla de forma horizontal encima de otra.

Más de 3 dimensiones es difícil de ejemplificar e imposible de pensar gráficamente, pero hay aplicaciones que usan este tipo de estructuras, algunas vinculadas con la matemática y la estadística.

Hemos dicho que un array multidimensional es un array dentro de otro. Entonces, ¿cómo se define? Veamos un ejemplo, con índices numéricos.

Se define un array y se hace que cada uno de los elementos sea otro array. Noten que los arrays que se definen dentro tienen todos la misma cantidad de elementos. Esto está vinculado a la aclaración que hice al principio.

Este array recién definido es una tabla con una lista de empleados. El primer elemento de los arrays que están dentro equivale a la columna nombre de una tabla. El segundo, a la columna edad, el tercero al puesto y el cuarto a la remuneración.

No hace falta definirlo de la manera en que lo hice yo, abriendo el primer array y poniendo los que van dentro uno por línea. Sin embargo, es lo más conveniente para que se vea de forma clara la estructura de la tabla.

¿Se puede definir un array multidimensional asociativo. Sí, de la siguiente forma.

Al array que contiene a los otros arrays no le puse clave y valor, pero podría tenerlo. Los que aparecen dentro sí tienen esa forma. Quizás de esta manera es un poco más difícil interpretar de un vistazo que eso es una tabla, pero es exactamente igual que hacerlo con índices numéricos.

Pero hablamos de índices numéricos y aún no hemos puesto ninguno. Están implícitos en el primer ejemplo. Si quisiéramos acceder a los elementos o celdas, podríamos utilizar la conocida nomenclatura de índices que ya vimos con los arrays.

Esta vez, tras el nombre del array, aparecen dos índices, uno pegado al otro. El primero indica el array que está dentro y el segundo el elemento o campo del mismo. En este ejemplo, el 0 indica que estamos apuntando a:

Este array, al que en este caso podemos llamar fila tiene índice 0, por ser el primero de todos. Recuerden que en PHP (y en todos los lenguajes) siempre se empieza a contar desde 0. El segundo índice es un 1 y hace referencia al segundo elemento de este array que es el número 25 y que representa la edad del empleado. Por lo tanto, ese es el número que saldrá impreso por pantalla cuando se ejecute esa línea.

Siguiendo la misma lógica:

Esto imprimirá en pantalla Gerente Comercial y:

Pondrá un 38 en lugar del número 37 que se había definido al principio.

Ahora con los asociativos, fíjense como pueden combinarse los tipos de índices.

Mostrará por pantalla Messi, Lionel.

Imprimirá por pantalla Santos.

Es decir que, así como podíamos acceder y utilizar los elementos de un array simple, también podremos hacerlo con arrays multidimensionales.

Recorrer arrays multidimensionales

Estas estructuras se ponen más interesantes cuando somos capaces de recorrerlas. Vamos a ver cómo hacer esto recorriendo, primero por filas y luego por columnas.

Recorrer con bucle for mediante índices numéricos

La estructura es la siguiente

Seguimos trabajando con el array $empleados definido al comienzo. Como hay dos arrays, uno dentro de otro, vamos a necesitar dos for, uno dentro de otro. Llamo $fila a la variable que cuenta por afuera y $col de columna, a la que cuenta por dentro. ¿Por qué? Porque cuando se usen como índices, la primera indicará la fila y la segunda la columna.

Prestemos atención al primer for. Empezamos a contar desde 0, incrementamos en uno hasta que llegamos a la cantidad de filas de $empleados menos uno. Se usa count para contar la cantidad de elementos del array. En este caso, nos dice cuantos elementos tiene el array de afuera. No olviden el  –1, porque si no, van a obtener un error de offset.

En el for interior, también se cuenta desde 0 y se incrementa en 1. Se contará hasta $empleados[$fila]-1. Es decir, hasta la cantidad de elementos que tenga el array $empleados[$fila].

En este ejemplo simplemente mostramos los elementos de los arrays por fila, separados de un guión o signo menos y dejando un fin de línea o “enter” al final de cada fila. El resultado es el siguiente:

Recorrer con bucle for mediante índices asociativos

No podemos usar for con índices asociativos, debido a que las claves de los elementos son cadenas de caracteres o números desordenados y no números enteros ordenados.

Como en este caso el primer índice sí es numérico, podremos utilizar el for externo, pero para el bucle interno, utilizaremos un foreach:

Se toma cada array $empleados[$i] para iterar cada uno de sus elementos con la variable $campo.

También, es bueno tener presente que se puede hacer lo siguiente:

Es posible iterar las filas y acceder a los campos como arrays asociativos. Aquí utilizamos la tabla jugadores y el resultado de esta porción de código es:

Recorrer con dos foreach

Al igual que los for, se pueden utilizar dos foreach, uno dentro de otro para recorrer tablas.

El valor del foreach de afuera pasa a ser el array del foreach de adentro y el valor del de adentro, es el elemento o celda de la tabla.

Recorrer con for y while

Como ven, siempre se utilizan dos bucles, a excepción del caso anterior con un for en el que se accede luego de forma particular a los campos. Ahora vamos a ver cómo recorrer con for por fuera y while por dentro.

Por fuera, el bucle for habitual. Por dentro vamos a usar una estructura que aún no expliqué, puesto que no suele ser habitual su uso, pero sirve para recorrer arrays.

La función each, que aparece a la derecha dentro de la condición del while obtiene clave y valor de un elemento del array que se pasa como parámetro. El resultado de esta función es otro array. Es importante entender que each pasa a un array unidimensional tanto las claves como los valores y los pone uno atrás de otro. Luego de hacer esto, mueve un puntero interno que tiene y lo deja apuntando al siguiente elemento del array original. Es decir que la próxima vez que se utilice devuelve la clave y el valor del siguiente elemento.

La función list, toma los elementos sucesivos de un array y los asigna a las variables que van como parámetro. En este caso, $clave y $valor, que tomarán los elementos devueltos por each. ¿Qué hace el reset que aparece arriba? Recién expliqué que each tiene un puntero interno que apunta a los elementos del array. Si se quiere recorrer el array, el manual de PHP dice que hay que utilizar reset antes de volver a utilizar each, y es por eso que aparece antes del while.

Si piensan un poco esta estructura, el resultado es el mismo que un foreach. Si bien el asunto es mucho más complejo e implica algunas consideraciones avanzadas sobre el lenguaje, podemos considerarlo de esta manera. Por lo tanto, mi consejo aquí es el siguiente. Estudiemos y entendamos qué hace esto y cómo funciona, pero tratemos de evitarlo y utilicemos en su lugar un foreach.

Imprimir tablas en HTML

Es muy común querer mostrar el array de dos dimensiones con los datos tabulados. Para eso es necesario utilizar la etiqueta <table>, de HTML. Vamos a ver cómo hacerlo con dos bucles for, pero se puede hacer también con los otros ciclos que hemos visto.

Recuerden utilizar la cabecera de la tabla con <thead> y los correspondientes <th>. El cuerpo de la tabla, es decir, el contenido va entre etiquetas <tbody> y </tbody>. Luego del for externo, aparecen las etiquetas <tr> que agrupan las filas. Tras el for interno, se ponen las celdas con las etiquetas <td>.

Agregar una fila

Cuando trabajamos con tablas nos puede interesar agregar una nueva fila. Eso lo podemos realizar de la siguiente forma

Se define por separado en un nuevo array la fila a agregar. Luego, se utiliza $empleados[] para agregarla al final.

Agregar una columna

Esto no es tan simple como el caso anterior, pero igual es posible realizarlo. Veamos cómo.

Trabajamos con el array $empleados tras haberle agregado una nueva fila, como expliqué recién. Vamos a definir una columna que no es más que una array que agrupa datos del mismo tipo y que tiene un elemento por cada fila de la tabla. En este caso, podemos tomar esta nueva columna como la fecha de ingreso de los empleados a sus actuales trabajos.

Se inicializa una variable $i en 0, que se usará como índice de la columna a agregar. Se hace un ciclo for para recorrer los empleados, de la forma que ya hemos visto. La manera de agregar las columnas la pueden ver a continuación. El índice $r en $empleados se refiere a la fila, luego podríamos poner un número 4, ya que sabemos que hay 3 columnas y que la que agregamos sería la cuarta, pero el count($empleados[$r]) es más genérico y nos evita tener que poner un literal. count($empleados[$r]) siempre devolverá un número más que la cantidad de columnas que existan, independientemente de las dimensiones de la tabla. En esa posición se agrega el ítem de la nueva columna y luego se corre el índice para la siguiente pasada.

Ordenamiento de tablas por columnas

Presentar los datos ordenados es una parte importante de cualquier pieza de software. En el uso de tablas esto se potencia y constituye una importante funcionalidad de los programas.

En la clase de arrays habíamos visto varias funciones de PHP que sirven para ordenar los datos. Una de ellas era sort. Si utilizamos sort en este tipo de estructuras de varios niveles, vamos a terminar ordenando por la primera columna. Veamos un ejemplo.

Si luego mostramos la tabla el resultado será el siguiente:

Nombre Edad Puesto Salario Ingreso
Alvarez, Susana 37 Gerente RR.HH. 1050000 19/11/2002
Cavallero, Antonio 45 Gerente comercial 350000 30/02/1999
Gomez, Maria 25 Administrativo 750000 02/05/2004
Ventura, Ernesto 18 Cadete 500000 12/06/1992

El ordenamiento se da por la primera columna, que se corresponde con el nombre. Por defecto, se realiza en orden alfabético, teniendo en cuenta que la primera columna es una cadena de caracteres. Si fueran números, se ordenarían en orden descendente.

Pero vamos a ver una técnica que se utiliza para ordenar las filas de una tabla según la columna que se prefiera.

Presten mucha atención a estas tres líneas. Vamos a utilizar un foreach para recorrer el array $empleados, descomponiendo sus elementos en clave y valor. No pierdan de vista que el valor es nada más y nada menos que cada una de las filas.

La siguiente línea lo que hace es pasar toda la columna 3 (la cuarta columna) a un nuevo array. $columnaOrden es un array que empieza vacío y en cada pasada va obteniendo cada uno de los valores de la cuarta columna de $empleados, es decir, los sueldos de cada empleado. Al finalizar el recorrido, $columnaOrden habrá copiado toda la columna de sueldos de los empleados.

En la siguiente línea, ya fuera del foreach, se utiliza la función array_multisort, una función de ordenamiento de PHP que sirve para ordenar varios arrays al mismo tiempo, o para ordenar un array multidimensional.

El primer parámetro será el array que tiene la columna en función de la cual se ordenará, el segundo parámetro indica el sentido de ordenamiento y el tercero, el array a ordenar. array_multisort liga las filas de $columnaOrden y de $empleados, de manera que al ordenar el primero, lo hace también con el segundo.

Nombre Edad Puesto Salario Ingreso
Alvarez, Susana 37 Gerente RR.HH. 1050000 19/11/2002
Gomez, Maria 25 Administrativo 750000 02/05/2004
Ventura, Ernesto 18 Cadete 500000 12/06/1992
Cavallero, Antonio 45 Gerente comercial 350000 30/02/1999

Como pueden apreciar, la tabla ahora aparece ordenada de acuerdo a la columna salario.

Si cambiáramos en el último código que vimos el índice de fila que está en 3, por 1, el ordenamiento se haría por la columna 1, es decir, la segunda columna, que indica la edad del empleado.

Nombre Edad Puesto Salario Ingreso
Cavallero, Antonio 45 Gerente comercial 350000 30/02/1999
Alvarez, Susana 37 Gerente RR.HH. 1050000 19/11/2002
Gomez, Maria 25 Administrativo 750000 02/05/2004
Ventura, Ernesto 18 Cadete 500000 12/06/1992

Arrays de 3 dimensiones

Por último, me gustaría mostrar un ejemplo de array de tres dimensiones y la forma de recorrerlo. La definición se puede hacer de la siguiente forma.

Nada nuevo en realidad. Imaginen una cadena de supermercados que tiene un sistema de compras online. Podría manejar arrays similares a estos.

Para recorrerlos, ahora en vez de dos bucles for, habrá tres.

Se mantiene la misma estructura que antes, pero se agrega un nivel más de anidación. En el tercer bucle for, ahora se cuenta hasta $productos[$i][$r]-1. No podemos visualizar esta estructura en una tabla, puesto que es un elemento tridimensional. Se necesitaría un prisma rectangular para representarlo visualmente.

Esto permite proyectar la forma de definir y recorrer arrays de n dimensiones.

Conclusiones

A lo largo de esta clase hemos visto como definir, recorrer y manipular arrays de dos dimensiones, también llamados tablas. Pueden ser definidas mediante índices numéricos o mediante arrays asociativos. Existen varias formas de recorrerlos: con dos bucles for, con dos bucles foreach, combinando ambos o incluso con un for, un while y la ayuda de las funciones each y list. Existen otras más, donde se pueden implementar while o do… while, pero generalmente no resulta cómodo para el programador ni óptimo para el programa.

También exploramos la forma de ordenar estas tablas a través de una técnica que permite hacerlo por columna.

Finalmente, vimos cómo son los arrays de tres dimensiones y proyectamos cómo pueden definirse y manipularse en más dimensiones.

Ejercicios propuestos

  1. Se muestra una tabla de 5 países con la siguiente información: número de identificación (un número entero de una o dos cifras), nombre, continente, población, superficie y dominio de internet. El usuario ingresa un número en un formulario que corresponde al número de identificación del país en la tabla. El mismo archivo recibe el formulario y deberá colorear la fila que corresponda al número de identificación. Sugerencia: Utilizar el atributo class de CSS para colorear la fila.
  2. Una disquería busca actualizar el precio de varios de sus títulos. Los discos están en un array $discos que tiene la siguiente estructura y contenido:

    Se tiene un array $actualizacion con la siguiente estructura y contenido:

    El id se corresponde con el id de $discos y el precio es el que se desea actualizar

    Se pide:
    a) Mostrar la lista de discos en una estructura de tabla.
    b) Realizar un algoritmo que tome ambos arrays multidimensionales y actualice el primero con los precios nuevos que trae el segundo.

  3. Dado el siguiente fixture de partidos de fútbol:

    Cada fila es un partido jugado donde las columnas indican lo siguiente:

    Equipo Local, Goles convertidos Local, Equipo visitante, Goles Convertidos Visitante
    Se pide:
    a) Armar la tabla de posiciones en en base a los resultados del fixture considerando las columnas: Partidos Jugados, Ganados, Empatados, Perdidos, Goles a favor, Goles en contra y Puntos sumados. (Partido ganado suma 3 puntos, empatado 1 y perdido 0)
    b) Mostrar la tabla de posiciones en orden por puntos en orden descendente.
    Sugerencia: Utilizar la función strcmp de PHP para identificar cada equipo al recorrer el fixture.

  4. Dada una matriz de 9 filas por 15 columnas que está vacía, generar para cada elemento un número al azar que solo puede ser 1 o 0. Mostrar la matriz por la pantalla utilizando <table> </table>. Recorrer cada columna sumando todos los elementos y determinar si la suma de cada columna es par o impar. Informar el resultado en cada columna agregando una fila al final de la tabla.
  5. Dada la siguiente tabla de empleados:

    Se pide realizar lo siguiente, en el orden que se indica.

    a) Obtener y mostrar el nombre del empleado que gana más dinero.
    b) Calcular el sueldo promedio de todos los empleados y mostrarlo por pantalla.
    c) Contar cuántos empleados administrativos hay (usar strcmp)
    d) Eliminar a los que ocupan puesto Mantenimiento (usar strcmp)
    e) Incrementar el sueldo de todos en un 25%.
    d) Mostrar la tabla luego de los cambios.

Bibliografía

  • Zend PHP5 Certification Study Guide de Davey Shafik con Ben Ramsey, php architect nanobooks
  • Desarrollo web con PHP y MySQL, de Luke Welling y Laura Thomson, Editorial Anaya
Soy programador web y me desempeño como Líder Técnico en Polar Bear Development. Trabajo con tecnologías como PHP, Javascript, MySQL y HTML5 para el desarrollo de sitios y sistemas web. Me especializo en Zend Framework 2 y otros frameworks MVC, como también en WordPress y otros CMS. Lidero equipos de desarrolladores trabajando con Scrum. Vivo en Buenos Aires, Argentina.
 

6 thoughts on “Curso de PHP: Nivel Básico – Clase 8. Arrays multidimensionales

  1. Podrías ayudarme con una duda?
    Si quisiera hacer una busqueda dentro de la matriz, por ejemplo que muestre el salario de Cavallero, Alejandro?
    Gracias
    Saludos

Deja un comentario

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


*