====== 02 - PHP V: Arrays ======
Un //array// en PHP es en realidad un mapa ordenado. Un mapa es un tipo de datos que asocia valores con claves. Este mapa se puede emplear como //array//, lista, tabla asociativa, diccionario, colección, pila, cola….
Como los valores de un //array// pueden ser otro //arrays//, podemos crear árboles y //arrays// multidimensionales.
Los valores no tienen porqué ser del mismo tipo de datos. Podemos crear un //array// donde se mezclen valores enteros con cadenas de caracteres. Incluso las claves pueden ser de diferentes tipos, como veremos más adelante.
Existen multitud de funciones en PHP para trabajar con //arrays//. Más adelante veremos algunas de las más útiles.
===== Declaración =====
Para declarar una variable de tipo //array// utilizamos el constructor **array()**. A continuación podemos escribir directamente los valores separados por coma, o definir las claves y sus valores. Para definir pares de clave – valor, usamos la notación //clave => valor//.
$a = array(9,12,34,56,78);
$b = array(
'a' => 9,
'b' => 12,
'c' => 34,
'd' => 56,
'e' => 78
);
Si utilizamos la primera forma (no definimos las claves), PHP asigna una clave de forma automática a cada elemento que será un entero dependiendo de la posición que ocupe el valor en el //array//, empezando por cero.
A partir de PHP 5.4 también se puede usar la sintaxis de //array// corta, la cual reemplazará //array()// por **[ ]**.
$c = [
'a' => 9,
'b' => 12,
'c' => 34,
'd' => 56,
'e' => 78
];
Las claves pueden ser un //integer// o un //string//. El valor puede ser de cualquier tipo (incluso otro //array//).
Hay que tener en cuenta los siguientes puntos para las claves:
* Un //string// que contenga un //integer// válido será convertido a //integer//. Por ejemplo, la clave “8” se transformará en 8. Sin embargo, la clave “08” no se convertirá en 8, ya que no es un //integer// válido.
* Un //float// eliminará la parte fraccionaria y se almacenará como la parte entera del número. Por ejemplo, la clave 7.3 se almacenará como 7.
* Un //booleano// también se almacenará como //integer//. La clave //true// = 1, y //false// = 0.
* Un clave //null// será almacenada como la cadena "".
* Si varios elementos en la declaración del //array// usan la misma clave, sólo se utilizará la última, eliminando los demás elementos.
$d = [
1 => 'Pepe',
1.5 => 'María',
true => 'Juan',
'1' => 'Amparo'
];
El //array// anterior se convertirá en:
$d = [
1 => 'Amparo'
];
Los //array// en PHP pueden contener claves //integer// y //string// al mismo tiempo, ya que PHP no distingue entre //arrays// indexados y asociativos (son todos asociativos).
$e = [
100 => 'Pepe',
101 => 'María',
'foo' => 'Juan',
'bar' => 'Amparo'
];
La clave es opcional. Si no se utiliza, PHP usará el incremento de la clave de tipo //integer// mayor utilizada anteriormente (si no hemos utilizado ninguna empezará por 0).
Por ejemplo, si definimos el siguiente //array//:
$f = array('Pepe', 'María', 'Juan', 'Amparo');
PHP lo convertirá en:
$f = [
0 => 'Pepe',
1 => 'María',
2 => 'Juan',
3 => 'Amparo'
];
Es posible especificar las claves para algunos elementos y excluir a los demás.
$f = [
'Pepe',
'María',
6 => 'Juan',
'Amparo'
];
El anterior //array// será equivalente a:
$f = [
0 => 'Pepe',
1 => 'María',
6 => 'Juan',
7 => 'Amparo'
];
La última clave es 7 y no 3 porque, como hemos dicho antes, PHP utiliza el mayor entero utilizado anteriormente para las claves. Al ser 6 el mayor entero, PHP incrementa en 1 esa clave, dando como resultado 7.
Podemos crear //arrays// multidimensionales definiendo a su vez los valores como //arrays//.
$h = [
[
"nombre" => 'Pepe',
"edad" => 25
],
[
"nombre" => 'María',
"edad" => 36
]
];
Podríamos pensar en poner claves a los //arrays// del segundo nivel para reducir el tamaño de la siguiente forma:
$h = [
"Pepe" => [
"edad" => 25
],
"María" => [
"edad" => 36
]
];
Aunque ésto tiene un problema evidente. Ya que no se pueden repetir las claves de los arrays, si añadiésemos una nueva persona llamada //María//, machacaría los datos anteriores, perdiendo datos en el proceso.
Por regla general, lo mejor es crear los //arrays// multidimensionales de la primera forma, simulando tablas donde las claves serían enteros que nos indicaría el número de registro.
===== Acceso =====
Para acceder a los elementos de un **array** lo hacemos mediante **$array[clave]**.
Dependiendo de si hemos definido las claves o no, podremos utilizar números secuenciales (empezando por 0) o nuestras propias claves:
$miArray = [3, 5, 67, 9, 48];
echo $miArray[0]; # imprimirá 3
echo $miArray[2]; # imprimirá 67
$miArray = [
"elemento1" => 2,
"elemento2" => 5,
"elemento3" => 67,
"elemento4" => 9,
"elemento5" => 48,
];
echo $miArray["elemento2"]; #imprimirá 5
echo $miArray["elemento5"]; #imprimirá 48
Para acceder a los elementos de los //array// multidimensionales tendremos que anidar tantas claves como niveles tenga el elemento al que queramos acceder.
$personas = [
[
"nombre" => "Pepe",
"edad" => 34
]
];
echo $personas[0]["nombre"]; #imprimirá Pepe
==== Recorrer un array ====
Aunque se puede recorrer un //array// con casi cualquier bucle, PHP nos ofrece un modo sencillo para iterar sobre ellos: [[https://www.php.net/manual/es/control-structures.foreach.php|foreach]].
Existen dos sintaxis:
foreach ($miArray as $value) {
# code...
}
foreach ($miArray as $key => $value) {
# code...
}
La diferencia es que en la primera obtenemos sólo los valores, mientras que con la segunda forma podemos acceder también a las claves del //array//.
Por ejemplo, si tenemos el siguiente //array//:
$contacto = [
"nombre" => "Pepe",
"edad" => 25,
"direccion" => "C/ Alcalá, 25",
"ciudad" => "Valencia"
];
Si recorremos el //array// con la primera forma:
foreach ($contacto as $value) {
echo "$value
";
};
La salida será:
{{ :clase:daw:dws:1eval:arrays01.png?200 |}}
Mientras que si lo recorremos de la segunda forma:
foreach ($contacto as $key => $value) {
echo "$key: $value
";
};
Podríamos sacar también las claves del //array// por pantalla:
{{ :clase:daw:dws:1eval:arrays02.png?200 |}}
===== Operadores para array =====
==== Unión ====
Para unir dos //array// utilizamos el operador **+**.
$arrayA = [
"primero" => 3,
"segundo" => 45,
"tercero" => 67,
"cuarto" => 8
];
$arrayB = [
"quinto" => 56,
"sexto" => 98,
"septimo" => 23,
"octavo" => 2
];
$resultado = $arrayA + $arrayB;
var_dump($resultado);
El //array// //$resultado// sería:
{{ :clase:daw:dws:1eval:arrays03.png?200 |}}
Hay que tener cuidado con el operador de unión para //arrays//. **Para las claves que existan en ambos //arrays//, serán utilizados los elementos del //array// de la izquierda y serán ignorados los elementos correspondientes del //array// de la derecha**.
Por ejemplo, si tenemos estos dos //arrays//:
$arrayA = [
"primero" => 3,
"segundo" => 45,
];
$arrayB = [
"primero" => 56,
"segundo" => 98,
"tercer" => 23,
];
$resultado = $arrayA + $arrayB;
var_dump($resultado);
El //array// //$resultado// no contendrá 5 elementos, como podríamos pensar a priori, si no que tendría sólo 3 elementos:
{{ :clase:daw:dws:1eval:arrays04.png?400 |}}
Como hemos visto antes, si no utilizamos claves en nuestros //arrays//, PHP les asigna claves numéricas consecutivas empezando por 0, con lo que los primeros elementos de los dos //arrays// tendrán la misma clave y no obtendremos el resultado esperado.
==== Comparadores de arrays ====
Para comparar //arrays// podemos utilizar los mismos operadores de comparación que para el resto de tipo de datos con alguna particularidad.
Si queremos saber si dos //arrays// son iguales, podemos usar //==// (igual que podemos utilizar //!=// para saber si son distintos), aunque puede haber alguna situación donde parezca que la comparación no funciona como debe.
Supongamos que tenemos el siguiente código:
$arrayA = [
"primero" => 3,
"segundo" => 45,
];
$arrayB = [
"segundo" => 45,
"primero" => 3,
];
if($arrayA == $arrayB) {
echo "Los arrays son iguales";
} else {
echo "Los arrays son diferentes";
}
Si vemos la salida que nos muestra el navegador, veremos que, al contrario de lo que podríamos pensar, los dos //arrays// son iguales:
{{ :clase:daw:dws:1eval:arrays05.png?200 |}}
Ésto ocurre porque el comparador //==// en //arrays// comprueba que tienen los mismos pares claves – valor, pero no el orden en el que están en cada //array//.
Si queremos comparar los //arrays// para saber si son exactamente idénticos, deberemos utilizar el operador //===//.
$arrayA = [
"primero" => 3,
"segundo" => 45,
];
$arrayB = [
"segundo" => 45,
"primero" => 3,
];
if($arrayA === $arrayB) {
echo "Los arrays son iguales";
} else {
echo "Los arrays son diferentes";
}
Cuya salida, ahora sí, es la esperada:
{{ :clase:daw:dws:1eval:arrays06.png?200 |}}
De todas formas, la mayoría de veces es más útil trabajar con funciones propias de los //arrays//, como veremos en el apartado siguiente.
===== Funciones de los arrays =====
Como hemos dicho, existen muchas funciones para trabajar con //arrays//. En este punto veremos algunas de ellas (podéis ver todas las que hay en el [[https://www.php.net/manual/es/ref.array.php|manual de php]]).
==== count ====
La función [[https://www.php.net/manual/es/function.count.php|count]] cuenta todos los elementos de un //array//. Podemos usar [[https://www.php.net/manual/es/function.sizeof.php|sizeof]] como alias de //count()//.
$miArray = [34, 3, 65, 7, 87, 99, 3];
$longitud = count($miArray);
echo "El array tiene $longitud elementos";
{{ :clase:daw:dws:1eval:arrays07.png?200 |}}
==== array_push ====
La función [[https://www.php.net/manual/es/function.array-push.php|array_push]] añade un elemento al final de un //array//.
$miArray = [34, 3, 65, 7, 87, 99, 3];
array_push($miArray, 100);
var_dump($miArray);
{{ :clase:daw:dws:1eval:arrays08.png?200 |}}
Podemos conseguir los mismo con //array[] = nuevo_elemento//.
$miArray = [34, 3, 65, 7, 87, 99, 3];
$miArray[] = 100;
==== array_values ====
La función [[https://www.php.net/manual/es/function.array-values.php|array_values]] devuelve todos los valores del //array// y lo indexa numéricamente.
$miArray = [
"foo" => 5,
"bar" => 7
];
var_dump(array_values($miArray));
{{ :clase:daw:dws:1eval:arrays09.png?200 |}}
==== array_keys ====
La función [[https://www.php.net/manual/es/function.array-keys.php|array_keys]] devuelve todas las claves de un //array// o un subconjunto de ellas.
$miArray = [
"foo" => 5,
"bar" => 7
];
var_dump(array_keys($miArray));
{{ :clase:daw:dws:1eval:arrays10.png?200 |}}
Podemos sacar las claves de un valor si especificamos el segundo parámetro.
$miArray = [
"foo" => 5,
"bar" => 7
];
var_dump(array_keys($miArray, 7));
{{ :clase:daw:dws:1eval:arrays11.png?200 |}}
==== in_array ====
La función [[https://www.php.net/manual/es/function.in-array.php|in_array]] comprueba si un valor existe en un //array//.
$miArray = [34, 3, 65, 7, 87, 99, 3];
if (in_array(65, $miArray)) {
echo "El valor existe en el array";
} else {
echo "El valor no existe en el array";
}
{{ :clase:daw:dws:1eval:arrays12.png?200 |}}
==== array_search ====
La función [[https://www.php.net/manual/es/function.array-search.php|array_search]] busca el valor en un //array// y devuelve su clave.
$miArray = [
"foo" => 5,
"bar" => 7,
"pre" => 18,
"dig" => 56
];
$clave = array_search(7, $miArray);
echo "La clave del elemento 7 es $clave";
{{ :clase:daw:dws:1eval:arrays13.png?200 |}}
==== array_key_exists ====
La función [[https://www.php.net/manual/es/function.array-key-exists.php|array_key_exists]] comprueba si la clave existe en el //array//. Podemos utilizar el alias [[https://www.php.net/manual/es/function.key-exists.php|key_exists]].
$miArray = [
"foo" => 5,
"bar" => 7,
"pre" => 18,
"dig" => 56
];
if (array_key_exists("dig", $miArray)) {
echo "La clave dig existe en el array";
} else {
echo "La clave dig no existe en el array";
}
{{ :clase:daw:dws:1eval:arrays14.png?200 |}}
==== sort ====
La función [[https://www.php.net/manual/es/function.sort.php|sort]] ordena un //array// de menor a mayor.
$frutas = array("limón", "naranja", "banana", "albaricoque");
sort($frutas);
var_dump($frutas);
{{ :clase:daw:dws:1eval:arrays15.png?200 |}}
==== array_merge ====
La función [[https://www.php.net/manual/es/function.array-merge.php|array_merge]] combina los elementos de uno o más //arrays// juntándolos de modo que los valores de uno se anexan al final del anterior. Los valores del //array// de entrada con claves numéricas serán renumeradas con claves incrementales en el //array// resultante, comenzando desde cero.
$arrayA = [3, 45, 67, 89];
$arrayB = [4, 65, 34, 98, 45];
$resultado = array_merge($arrayA, $arrayB);
var_dump($resultado);
{{ :clase:daw:dws:1eval:arrays16.png?200 |}}
Si los //arrays// de entrada tienen las mismas claves de tipo //string//, el último valor para esa clave sobrescribirá al anterior.
$arrayA = [
"primero" => 3,
"segundo" => 45,
];
$arrayB = [
"primero" => 56,
"segundo" => 98,
"tercera" => 23,
];
$resultado = array_merge($arrayA, $arrayB);
var_dump($resultado);
{{ :clase:daw:dws:1eval:arrays17.png?200 |}}
==== array_diff ====
La función [[https://www.php.net/manual/es/function.array-diff.php|array_diff]] compara //array1// con uno o más //arrays// y devuelve los valores de //array1// que no estén presentes en ninguno de los otros //arrays//.
$arrayA = ["green", "red", "blue", "red"];
$arrayB = ["green", "yellow", "red"];
$resultado = array_diff($arrayA, $arrayB);
var_dump($resultado);
{{ :clase:daw:dws:1eval:arrays18.png?200 |}}
===== Ejercicios =====
**Ejercicio 1**
Escribe un programa en PHP que genere un //array// de un número aleatorio de valores numéricos (entre 5 y 15). Los valores se encontraran entre 0 y 10, también obtenidos de forma aleatoria.
Salida:
{{ :clase:daw:dws:1eval:arrays19.png?200 |}}
**Ejercicio 2**
Crea un archivo PHP que almacene en un //array// la tabla de multiplicar del 7. El programa deberá sacar por pantalla dicha tabla.
**Ejercicio 3**
Modifica el ejercicio anterior para que se almacene en una matriz las tablas de multiplicar del 1 al 9 y las muestre por pantalla.
**Ejercicio 4**
Una empresa quiere actualizar su gestión de almacén. Hasta ahora, iban apuntando en una hoja de cálculo el material que quedaba después de retirarlo de las estanterías (si no se retiraba algún material, no se apuntaba ese mes). Los datos de los dos meses que lleva abierta son:
Mayo:
* Tornillos = 57
* Tuercas = 23
* Clavos = 45
* Arandelas = 56
* Muelles = 32
Junio:
* Tornillos = 32
* Arandelas = 51
* Bridas = 309
Hacer un programa en PHP para que nos muestre el total de material que queda en junio en el almacén.
**Ejercicio 5**
Un restaurante quiere añadir el postre a todos sus menús (actualmente tienen menús con y sin postre). En su web, hecha con PHP, tienen el siguiente //array// con los diferentes menús:
$menus = [
[
"primero" => "sopa",
"segundo" => "carne",
"postre" => "tarta"
],
[
"primero" => "ensalada",
"segundo" => "carne",
],
[
"primero" => "macarrones",
"segundo" => "pescado",
],
[
"primero" => "sopa",
"segundo" => "pescado",
"postre" => "flan"
],
];
Escribe el código necesario para que, de forma lo más eficiente posible, nos muestre los menús que no tienen postre actualmente (los menús se numeran de forma correlativa empezando por el 1).
**Ejercicio 6**
Dado los dos siguientes arrays:
$array1 = [34, 56, 78, 8, 98, 33, 45];
$array2 = [56, 76, 2, 68, 77, 25, 15];
Escribir un programa en PHP que combine ambos //arrays// (con elemento repetidos si los hubiera) y los ordene de mayor a menor.
**Ejercicio 7**
Crea un fichero PHP llamado //ejercicio7a.php// con el siguiente contenido:
$empleados = [
[
"nombre" => "Juan",
"edad" => 34,
],
[
"nombre" => "María",
"edad" => 22
],
[
"nombre" => "Ángeles",
"edad" => 45
],
[
"nombre" => "Pepe",
"edad" => 34,
],
[
"nombre" => "Mario",
"edad" => 57
]
];
En otro fichero llamado //ejercicio7b.php//, escribe un programa PHP que muestre por pantalla el nombre y la edad del empleado más joven y del más mayor.