Funciones de arrays en PHP
En esta lección
PHP trae más de setenta funciones para trabajar con arrays. No hace falta aprenderlas todas: con una veintena resolverás casi cualquier tarea sin escribir bucles a mano. En esta lección verás las imprescindibles, agrupadas por lo que hacen: buscar, añadir y quitar, combinar, ordenar y transformar. Si todavía no sabes crear un array o recorrerlo con foreach, empieza por Arrays.
Dos tipos de funciones: las que modifican y las que devuelven
Antes de empezar, una idea que te ahorrará muchos errores. Las funciones de arrays de PHP se comportan de dos maneras:
- Unas modifican el array original y no devuelven el resultado (como mucho,
true). Son las de ordenar (sort,usort…) y las de añadir o quitar por los extremos (array_push,array_pop…). - Otras devuelven un array nuevo y dejan el original intacto:
array_map,array_filter,array_merge,array_slice…
$tallas = ["L", "S", "M"];
$resultado = sort($tallas);
var_dump($resultado);
echo implode(", ", $tallas), "\n";
// bool(true)
// L, M, S
sort() ha ordenado $tallas directamente y ha devuelto true. Si hubieras escrito $tallas = sort($tallas);, habrías perdido el array. Cuando dudes, la documentación oficial (php.net) indica en cada función si recibe el array por referencia (array &$array), que significa que lo modifica.
En los ejemplos usaremos implode(", ", $array) para mostrar listas sencillas en una línea y print_r() para ver arrays con claves.
Contar, sumar y buscar
count, array_sum, max y min
$minutosEntreno = [45, 60, 30, 90, 50];
echo count($minutosEntreno), " sesiones\n";
echo array_sum($minutosEntreno), " minutos en total\n";
echo max($minutosEntreno), " como máximo\n";
echo min($minutosEntreno), " como mínimo\n";
echo array_sum($minutosEntreno) / count($minutosEntreno), " de media\n";
// 5 sesiones
// 275 minutos en total
// 90 como máximo
// 30 como mínimo
// 55 de media
array_product() hace lo mismo que array_sum() pero multiplicando. Cuidado con calcular la media de un array vacío: dividirías entre cero y PHP 8 lanzaría un DivisionByZeroError. Comprueba antes que count() no es cero.
in_array: ¿está este valor?
in_array($valor, $array) devuelve true o false. Pasa siempre true como tercer argumento para que compare también el tipo, igual que ===:
$codigosValidos = ["10", "20", "30"];
var_dump(in_array(10, $codigosValidos));
var_dump(in_array(10, $codigosValidos, true));
var_dump(in_array("10", $codigosValidos, true));
// bool(true)
// bool(false)
// bool(true)
Sin el true, PHP compara con == y da por bueno el entero 10 aunque en el array haya una cadena. Con datos que llegan de formularios esto puede dejar pasar valores que no esperas.
array_search: ¿en qué posición está?
array_search() devuelve la clave donde está el valor, o false si no lo encuentra. Aquí hay una trampa clásica:
$cola = ["Lucía", "Andrés", "Marta"];
$posicion = array_search("Lucía", $cola, true);
if (!$posicion) {
echo "Lucía no está en la cola\n";
}
if ($posicion === false) {
echo "Ahora sí: no está\n";
} else {
echo "Lucía está en la posición $posicion\n";
}
// Lucía no está en la cola
// Lucía está en la posición 0
Lucía está en la posición 0, y 0 cuenta como falso. Compara siempre con === false.
Claves: array_key_exists, array_keys y array_values
$stock = ["cuerda" => 4, "arnés" => 0, "casco" => null];
var_dump(array_key_exists("casco", $stock));
var_dump(isset($stock["casco"]));
echo implode(", ", array_keys($stock)), "\n";
echo implode(", ", array_keys($stock, 0, true)), "\n";
// bool(true)
// bool(false)
// cuerda, arnés, casco
// arnés
array_key_exists()dice si la clave existe, valga lo que valga.isset()devuelvefalsesi la clave no existe o si su valor esnull. Es más rápido y suele bastar, pero conoce la diferencia.array_keys()devuelve las claves; con un segundo argumento, solo las claves de los elementos con ese valor.array_values()devuelve los valores con claves nuevas0, 1, 2.... Lo usarás para “renumerar” un array.
array_key_first() y array_key_last() devuelven la primera y la última clave sin recorrer nada.
Añadir, quitar y extraer
Para añadir al final, lo habitual es $array[] = valor;. Para el resto de operaciones en los extremos hay cuatro funciones que modifican el array:
| Función | Qué hace | Devuelve |
|---|---|---|
array_push($a, $v) | Añade al final | El nuevo tamaño |
array_pop($a) | Quita el último | El elemento quitado |
array_unshift($a, $v) | Añade al principio | El nuevo tamaño |
array_shift($a) | Quita el primero | El elemento quitado |
$turnos = ["Iker", "Sara"];
array_unshift($turnos, "Nora");
$turnos[] = "Pablo";
$atendido = array_shift($turnos);
echo "Atendido: $atendido\n";
echo "En espera: ", implode(", ", $turnos), "\n";
// Atendido: Nora
// En espera: Iker, Sara, Pablo
array_slice: un trozo sin modificar el original
array_slice($array, $inicio, $cantidad) devuelve una parte del array. Es perfecto para “los tres primeros”:
$ranking = ["Ane", "Hugo", "Leire", "Mario", "Olga", "Raúl"];
echo implode(", ", array_slice($ranking, 0, 3)), "\n";
echo implode(", ", array_slice($ranking, -2)), "\n";
// Ane, Hugo, Leire
// Olga, Raúl
Un inicio negativo cuenta desde el final. Su pariente array_splice() sí modifica el original: quita (y opcionalmente sustituye) un tramo.
Combinar arrays
array_merge y el operador spread
$manana = ["yoga", "pilates"];
$tarde = ["spinning", "yoga"];
$todas = array_merge($manana, $tarde);
$tambien = [...$manana, ...$tarde];
echo implode(", ", $todas), "\n";
echo implode(", ", array_unique($todas)), "\n";
// yoga, pilates, spinning, yoga
// yoga, pilates, spinning
El operador spread (...) desempaqueta un array dentro de otro. Hace lo mismo que array_merge() y es la forma moderna. array_unique() quita los repetidos (conserva las claves originales; si necesitas 0, 1, 2..., pásalo por array_values()).
Con arrays asociativos, si una clave se repite, gana el último. Eso sirve para aplicar valores por defecto:
$porDefecto = ["idioma" => "es", "tema" => "claro", "avisos" => true];
$elegido = ["tema" => "oscuro"];
$config = array_merge($porDefecto, $elegido);
print_r($config);
// Array
// (
// [idioma] => es
// [tema] => oscuro
// [avisos] => 1
// )
Cuidado: el operador
+también une arrays, pero al revés: si una clave se repite, gana el primero, y con arrays numéricos ignora los elementos cuyas posiciones ya existen.[1, 2] + [3, 4, 5]da[1, 2, 5]. Para listas usa siemprearray_mergeo....
Para crear arrays asociativos a partir de listas tienes array_combine($claves, $valores), que une dos listas del mismo tamaño, array_fill_keys($claves, $valorInicial), ideal para contadores, y array_flip(), que intercambia claves y valores.
Diferencia e intersección
$inscritos = ["Ane", "Hugo", "Leire", "Mario"];
$pagados = ["Hugo", "Mario"];
echo "Deben la cuota: ", implode(", ", array_diff($inscritos, $pagados)), "\n";
echo "Al día: ", implode(", ", array_intersect($inscritos, $pagados)), "\n";
// Deben la cuota: Ane, Leire
// Al día: Hugo, Mario
array_diff() devuelve lo que está en el primero pero no en el segundo; array_intersect(), lo que está en los dos. Para comparar por claves existen array_diff_key() y array_intersect_key().
Ordenar
Todas las funciones de ordenación modifican el array y devuelven true. Cambian en dos cosas: si ordenan por valor o por clave, y si conservan la asociación entre clave y valor.
| Función | Ordena por | Orden | Conserva claves |
|---|---|---|---|
sort / rsort | Valor | Ascendente / descendente | No (renumera) |
asort / arsort | Valor | Ascendente / descendente | Sí |
ksort / krsort | Clave | Ascendente / descendente | Sí |
usort | Lo que tú digas | Lo que tú digas | No |
uasort / uksort | Lo que tú digas | Lo que tú digas | Sí |
La regla práctica: con listas usa sort; con arrays asociativos usa asort o ksort, porque sort tiraría las claves.
$puntos = ["Ane" => 72, "Hugo" => 95, "Leire" => 88];
arsort($puntos);
print_r($puntos);
ksort($puntos);
echo implode(", ", array_keys($puntos)), "\n";
// Array
// (
// [Hugo] => 95
// [Leire] => 88
// [Ane] => 72
// )
// Ane, Hugo, Leire
Nota: con textos, las mayúsculas van antes que las minúsculas y “foto10” antes que “foto2”.
sort($a, SORT_NATURAL | SORT_FLAG_CASE)lo arregla. Para tildes y eñes existe la claseCollatorde la extensiónintl.
usort: tu propio criterio
Cuando ordenas arrays de arrays (por ejemplo, filas que vienen de una base de datos), le pasas a usort() una función que compara dos elementos. Lo más cómodo es el operador nave espacial <=>, que devuelve -1, 0 o 1:
$rutas = [
["nombre" => "Peña Cabarga", "km" => 9.5, "desnivel" => 480],
["nombre" => "Faro del Caballo", "km" => 7, "desnivel" => 300],
["nombre" => "Pico Valnera", "km" => 14, "desnivel" => 900],
];
usort($rutas, fn($a, $b) => $a["km"] <=> $b["km"]);
echo implode(", ", array_column($rutas, "nombre")), "\n";
usort($rutas, fn($a, $b) => $b["desnivel"] <=> $a["desnivel"]);
echo implode(", ", array_column($rutas, "nombre")), "\n";
// Faro del Caballo, Peña Cabarga, Pico Valnera
// Pico Valnera, Peña Cabarga, Faro del Caballo
fn($a, $b) => ... es una función flecha: una función corta, sin nombre, que devuelve la expresión de la derecha. La verás a fondo en Funciones. Para orden descendente, basta con intercambiar $a y $b.
Para ordenar por dos criterios, compara arrays: [$a["nivel"], $a["nombre"]] <=> [$b["nivel"], $b["nombre"]] ordena por nivel y, si empatan, por nombre.
Transformar y filtrar
array_column: sacar una columna
Has visto array_column() en el ejemplo anterior. Extrae un campo de cada elemento de un array de arrays, y con un tercer argumento usa otro campo como clave:
$socios = [
["id" => 7, "nombre" => "Irene", "cuota" => 39.9],
["id" => 12, "nombre" => "Unai", "cuota" => 29.9],
];
print_r(array_column($socios, "nombre", "id"));
// Array
// (
// [7] => Irene
// [12] => Unai
// )
array_map: aplicar una función a cada elemento
array_map($funcion, $array) devuelve un array nuevo con el resultado de aplicar la función a cada elemento. Fíjate en que la función va primero:
$precios = [12.5, 40, 8.99];
$conIva = array_map(fn($p) => round($p * 1.21, 2), $precios);
echo implode(" | ", $conIva), "\n";
$nombres = [" ane ", "HUGO", "leire "];
$limpios = array_map(fn($n) => ucfirst(strtolower(trim($n))), $nombres);
echo implode(", ", $limpios), "\n";
// 15.13 | 48.4 | 10.88
// Ane, Hugo, Leire
También acepta el nombre de una función de PHP como cadena: array_map('trim', $nombres).
array_filter: quedarse con algunos
array_filter($array, $funcion) devuelve los elementos para los que la función devuelve true. Aquí el array va primero (sí, el orden de los argumentos de PHP es poco coherente; el editor te ayudará):
$temperaturas = ["lun" => 14, "mar" => 22, "mie" => 9, "jue" => 25];
$calurosos = array_filter($temperaturas, fn($t) => $t >= 20);
print_r($calurosos);
$notas = [7, 4, 9, 3];
$aprobadas = array_filter($notas, fn($n) => $n >= 5);
var_dump(array_key_first($aprobadas));
echo implode(", ", array_values($aprobadas)), "\n";
// Array
// (
// [mar] => 22
// [jue] => 25
// )
// int(0)
// 7, 9
array_filter() conserva las claves. En una lista, las aprobadas quedan en las posiciones 0 y 2, con un hueco en el 1. Si después vas a recorrerla con for o a convertirla en JSON, pásala por array_values().
Sin función, array_filter() elimina los valores que cuentan como falsos ("", 0, null, false…). Es un atajo para limpiar campos vacíos, pero ojo, también quita los ceros.
array_reduce: reducir a un único valor
array_reduce() recorre el array acumulando un resultado. El primer parámetro de la función es el acumulado; el segundo, el elemento actual; el tercer argumento de array_reduce es el valor inicial:
$carrito = [
["producto" => "Pies de gato", "precio" => 89, "unidades" => 1],
["producto" => "Magnesio", "precio" => 6.5, "unidades" => 3],
];
$total = array_reduce(
$carrito,
fn($suma, $linea) => $suma + $linea["precio"] * $linea["unidades"],
0
);
echo "Total: $total €\n";
// Total: 108.5 €
Novedades de PHP 8.4: array_find, array_any y array_all
PHP 8.4 añadió cuatro funciones que antes obligaban a escribir un bucle:
$reservas = [
["nombre" => "Ane", "personas" => 2, "pagada" => true],
["nombre" => "Hugo", "personas" => 6, "pagada" => false],
["nombre" => "Olga", "personas" => 4, "pagada" => true],
];
$grande = array_find($reservas, fn($r) => $r["personas"] > 3);
echo $grande["nombre"], "\n";
var_dump(array_any($reservas, fn($r) => !$r["pagada"]));
var_dump(array_all($reservas, fn($r) => $r["personas"] <= 6));
// Hugo
// bool(true)
// bool(true)
array_find()devuelve el primer elemento que cumple la condición (onull).array_find_key()devuelve su clave.array_any(): ¿alguno la cumple?array_all(): ¿todos la cumplen?
Si tu hosting tiene PHP 8.3 o anterior, no existen; comprueba la versión con php -v, como viste en Servidor local.
Otras funciones útiles
echo implode(", ", range(1, 5)), "\n";
echo implode(", ", range(0, 20, 5)), "\n";
echo implode(", ", range("a", "e")), "\n";
$grupos = array_chunk(["Ane", "Hugo", "Leire", "Mario", "Olga"], 2);
echo count($grupos), " grupos; el último: ", implode(", ", $grupos[2]), "\n";
echo implode(", ", array_reverse([1, 2, 3])), "\n";
echo json_encode(array_count_values(["S", "M", "M", "L", "M"])), "\n";
// 1, 2, 3, 4, 5
// 0, 5, 10, 15, 20
// a, b, c, d, e
// 3 grupos; el último: Olga
// 3, 2, 1
// {"S":1,"M":3,"L":1}
range() genera secuencias, array_chunk() parte un array en trozos, array_reverse() le da la vuelta y array_count_values() cuenta cuántas veces aparece cada valor. Además:
explode()eimplode()convierten entre cadena y array; las tienes en Cadenas.shuffle()desordena el array al azar (lo modifica) yarray_rand()elige una o varias claves al azar.
Ejemplo completo: estadísticas de una clase
Juntamos varias funciones para analizar las notas de un examen sin escribir ni un bucle:
$notas = [
"Ane" => 8.5, "Hugo" => 4, "Leire" => 9.25,
"Mario" => 6, "Olga" => 3.5, "Raúl" => 7,
];
$aprobados = array_filter($notas, fn($n) => $n >= 5);
arsort($aprobados);
$media = array_sum($notas) / count($notas);
echo "Media: ", round($media, 2), "\n";
echo "Aprobados: ", count($aprobados), " de ", count($notas), "\n";
echo "Podio: ", implode(", ", array_slice(array_keys($aprobados), 0, 3)), "\n";
echo "Suspensos: ", implode(", ", array_keys(array_diff_key($notas, $aprobados))), "\n";
// Media: 6.38
// Aprobados: 4 de 6
// Podio: Leire, Ane, Raúl
// Suspensos: Hugo, Olga
Errores frecuentes
- Guardar el resultado de
sort():$a = sort($a);deja$avaliendotrue. Las funciones de ordenar modifican el array y no lo devuelven. - Usar
sort()con un array asociativo: pierdes las claves. Usaasort()oksort(). - Comprobar
array_search()conif (!$pos): si el elemento está en la posición0, parece que no está. Compara con=== false. - Olvidar el
truedein_array(): sin él compara con==y acepta valores de otro tipo. - Confundir el orden de argumentos:
array_map($funcion, $array)peroarray_filter($array, $funcion). - Huecos tras
array_filter()oarray_unique(): conservan las claves. Usaarray_values()si necesitas0, 1, 2.... - Unir listas con
+: ignora los elementos cuyas posiciones ya existen. Usaarray_merge()o[...$a, ...$b].
Resumen
| Tarea | Funciones |
|---|---|
| Contar y calcular | count, array_sum, array_product, max, min |
| Buscar valores | in_array(..., true), array_search (compara con === false) |
| Claves | array_key_exists, array_keys, array_values, array_key_first, array_key_last |
| Extremos (modifican) | array_push, array_pop, array_unshift, array_shift |
| Trozos | array_slice (copia), array_splice (modifica), array_chunk |
| Combinar | array_merge, [...$a, ...$b], array_combine, array_fill_keys, array_flip |
| Comparar | array_unique, array_diff, array_intersect |
| Ordenar (modifican) | sort, rsort, asort, arsort, ksort, krsort, usort con <=> |
| Transformar | array_map, array_column, array_reverse |
| Filtrar y reducir | array_filter, array_reduce |
| PHP 8.4 | array_find, array_find_key, array_any, array_all |
En la siguiente lección aprenderás a escribir tus propias funciones: funciones.
Pon a prueba lo que has aprendido
¿Te ha quedado claro? Márcala y verás tu progreso en el explorador.