Filtrer les éléments d'un tableau

Pour filtrer les éléments d'un tableau, on fait habituellement :

$numbers = [0, 1, 2, 3, 4];

$even = [];
foreach ($numbers as $number) {
    if ($number%2 === 0) {
        $even[] = $number;
    }
}

/* Résultat :
array (
  0 => 0,
  1 => 2,
  2 => 4,
)
*/

Cette manière d'écrire est tout à fait valable, mais je vais vous proposer une autre possibilité : l'utilisation de la fonction array_filter.

array_filter() va vous permettre de filtrer les éléments d'un tableau grâce à une fonction de callback.

Il prend en premier argument le tableau d'origine et en second argument la fonction de rappel à appliquer sur chaque élément pour savoir si on le garde ou non.

Pour avoir le même résultat que ci-dessus, je vais faire :

$even = array_filter(
    $numbers,
    fn($number) => $number%2 === 0 
);

Attention toutefois : array_filter conserve les clés de chaque valeur gardée. Donc le code ci-dessus va retourner :

array (
  0 => 0,
  2 => 2,
  4 => 4,
)

Si l'on veut réinitialiser les clés, il faut faire un appel à array_values;

$even = array_filter(
    $numbers,
    fn($number) => $number%2 === 0 
);

$even = array_values($even);

/* Résultat :
array (
  0 => 0,
  1 => 2,
  2 => 4,
)
*/

Quelle est donc la meilleure façon de filtrer un tableau ?

La réponse est simple : il n'y a pas de meilleure façon.

J'aime bien utiliser array_filter car cette fonction m'évite d'avoir une variable qui "traîne" (déclaration + affectation de chaque valeur). Ici j'ai directement le résultat.

Si j'ai par exemple une fonction qui me fait ce filtrage, alors je n'ai même plus de variable intermédiaire, je peux retourner directement le résultat d'array_filter :

function getEvenNumbers(
    array $numbers
): array
{
  return array_filter(
    $numbers,
    fn($number) => $number%2 === 0 
  );
}

Et si je souhaite filtrer en utilisant les clés au lieu des valeurs ? ou les deux ?

Si votre filtrage utilise plutôt les clés du tableau que ses valeurs pour déterminer si on garde un élément, alors array_filter a une option pour vous.

Si on veut récupérer par exemple que les entrées d'un tableau dont leurs clés sont pairs, on va utiliser le flag ARRAY_FILTER_USE_KEY

$names = [
    2 => 'John',
    3 => 'Jane',
    8 => 'Bob',
    9 => 'John',
];

array_filter(
    $names,
    fn($key) => $key%2 === 0,
    ARRAY_FILTER_USE_KEY
);

/* Résultat
array (
  2 => 'John',
  8 => 'Bob',
)
*/

On peut aussi demander à array_filter de passer à la callback la clé et la valeur de chaque élément via le flag ARRAY_FILTER_USE_BOTH:

array_filter(
    $names,
    fn($name, $key) => $key%2 === 0 && $name === 'John',
    ARRAY_FILTER_USE_BOTH
);

/* Résultat : 
array (
  2 => 'John',
)
*/

Attention à son comportement "par défaut"

La callback n'est pas obligatoire lors de l'appel à array_filter, et dans ce cas, il va donc ignorer tous les éléments qui sont "vide".

$list = [
    1,
     'John',
     0,
     null,
     'Jane',
     ''
 ];
 
$filtered = array_filter($list);

/* Résultat : 
array (
  0 => 1,
  1 => 'John',
  4 => 'Jane',
)
*/

Soyez donc très vigilant, ce comportement par défaut est source de bugs et je vous conseille de toujours passez une callback.

Vous aimeriez progresser en PHP ? Mais vous ne savez pas comment vous y prendre ?

S'entraîner pour progresser en PHP

Mon programme "S'entraîner pour progresser en PHP" est disponible. Il vous permettra de recevoir chaque semaine un kata de code directement dans votre boîte mail, ainsi que des aides à la réalisation, des vidéos explicatives et des défis supplémentaires.

Reçois dès maintenant un kata gratuit en cliquant sur le bouton ci-dessous.