Saltar al contenido
funciones-de-arrays.php · devschool

Funciones de arrays en PHP

Lección 10 de 26 · 14 min de lectura · Actualizado el

En esta lección
  1. Dos tipos de funciones: las que modifican y las que devuelven
  2. Contar, sumar y buscar
  3. Añadir, quitar y extraer
  4. Combinar arrays
  5. Ordenar
  6. Transformar y filtrar
  7. Otras funciones útiles
  8. Ejemplo completo: estadísticas de una clase
  9. Errores frecuentes
  10. Resumen

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() devuelve false si la clave no existe o si su valor es null. 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 nuevas 0, 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ónQué haceDevuelve
array_push($a, $v)Añade al finalEl nuevo tamaño
array_pop($a)Quita el últimoEl elemento quitado
array_unshift($a, $v)Añade al principioEl nuevo tamaño
array_shift($a)Quita el primeroEl 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 siempre array_merge o ....

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ónOrdena porOrdenConserva claves
sort / rsortValorAscendente / descendenteNo (renumera)
asort / arsortValorAscendente / descendenteSí
ksort / krsortClaveAscendente / descendenteSí
usortLo que tú digasLo que tú digasNo
uasort / uksortLo que tú digasLo que tú digasSí

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 clase Collator de la extensión intl.

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 (o null). 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() e implode() convierten entre cadena y array; las tienes en Cadenas.
  • shuffle() desordena el array al azar (lo modifica) y array_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 $a valiendo true. Las funciones de ordenar modifican el array y no lo devuelven.
  • Usar sort() con un array asociativo: pierdes las claves. Usa asort() o ksort().
  • Comprobar array_search() con if (!$pos): si el elemento está en la posición 0, parece que no está. Compara con === false.
  • Olvidar el true de in_array(): sin él compara con == y acepta valores de otro tipo.
  • Confundir el orden de argumentos: array_map($funcion, $array) pero array_filter($array, $funcion).
  • Huecos tras array_filter() o array_unique(): conservan las claves. Usa array_values() si necesitas 0, 1, 2....
  • Unir listas con +: ignora los elementos cuyas posiciones ya existen. Usa array_merge() o [...$a, ...$b].

Resumen

TareaFunciones
Contar y calcularcount, array_sum, array_product, max, min
Buscar valoresin_array(..., true), array_search (compara con === false)
Clavesarray_key_exists, array_keys, array_values, array_key_first, array_key_last
Extremos (modifican)array_push, array_pop, array_unshift, array_shift
Trozosarray_slice (copia), array_splice (modifica), array_chunk
Combinararray_merge, [...$a, ...$b], array_combine, array_fill_keys, array_flip
Comparararray_unique, array_diff, array_intersect
Ordenar (modifican)sort, rsort, asort, arsort, ksort, krsort, usort con <=>
Transformararray_map, array_column, array_reverse
Filtrar y reducirarray_filter, array_reduce
PHP 8.4array_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

[PHP] ¿Qué muestra este código?
$a = [3, 1, 2];
$a = sort($a);
var_dump($a);

[PHP] ¿Qué muestra este código con el operador + entre arrays?
echo json_encode([1, 2] + [5, 6, 7]);

[PHP] ¿Qué valor tiene $total?
$total = array_reduce([1, 2, 3], fn($suma, $n) => $suma + $n * 2, 10);

[PHP] El elemento buscado puede estar en la posición 0. ¿Cómo compruebas bien que array_search no lo encontró?

¿Te ha quedado claro? Márcala y verás tu progreso en el explorador.