array_map avec plusieurs tableaux et fonction fléchée

Utilisation avancée de fonctions natives de PHP : array_map et array_filter

→ Challenge Correction: Affaire BL4CKWELL – Comte Vermillon

Pour ce premier challenge de l’édition 2015 de Top Code, on avait à disposition 2 tableaux de mots. Il fallait parcourir ces 2 tableaux pour comparer les mots un à un. Si un mot différait d’un tableau à l’autre, il fallait alors récupérer la première lettre de chaque mot pour les concaténer dans la réponse finale.

Première solution, avec une boucle foreach

« Des tableaux à parcourir », faire une boucle foreach semble être une bonne idée ! Et ça l’est ! On pouvait résoudre le challenge de cette façon :

// On prépare la réponse finale
$reponse = '';

// On boucle sur un des tableaux
foreach ($originals as $i => $word) {
    
    // Si les mots sont différents
    if ($word !== $recording[$i]) {
        
        // Concaténation
        $reponse .= substr($recording[$i], 0, 1);
        $reponse .= substr($word, 0, 1);
    }
}

// Affichage de la réponse
echo $reponse;

Un peu d’explications :

  • On prépare une chaine de caractères vide, $reponse, dans laquelle on va venir concaténer par la suite.
  • Je choisis un des 2 tableaux à parcourir. Le point clé ici est de bien récupérer l’index également, $i, qui nous servira à atteindre l’élément de même position dans l’autre tableau.
  • S’il y a une différence, alors on récupère les premières lettres avec la fonction substr.

Un challenge est toujours une bonne occasion pour mettre en pratique des concepts et outils plus avancés.

Travaillons une solution sans boucle, avec des fonctions qui traitent directement les tableaux en PHP.

Deuxième solution avec array_map et array_filter

La fonction array_map permet d’appliquer une fonction sur un tableau. Ce qu’on utilise un peu moins souvent, c’est le fait qu’elle peut appliquer une fonction sur plusieurs tableaux d’un coup.

Voici comment la mettre en oeuvre pour ce challenge :

// array_map et fonction fléchée
$words = array_map(
            fn($orig, $rec) => $orig !== $rec ? $rec[0] . $orig[0] : null,
            $originals,
            $recording
        );

// array_filter, sans fonction de filtre
$words = array_filter($words);

// implode pour afficher la réponse
echo implode($words);

Un peu d’explications :

  • array_map parcours en parallèle $originals et $recording et renvoie, pour chaque paire, soit la concaténation du premier caractère de l’enregistrement et de l’original (si différents), soit null.
  • array_filter est très souvent utilisé avec une fonction en deuxième paramètre, qui permet de déterminer si on conserve ou non un élément du tableau. Si on ne met pas de fonction, c’est comme si on appliquait « empty » sur chaque élément. Ici, empty(null) va donner true, donc l’élément sera retiré.
  • implode prend habituellement en premier paramètre la « glue » qui servira à coller les éléments entre eux. Mais implode peut prendre un seul paramètre, un tableau, et alors la glue est un caractère vide. Néanmoins, ce n’est pas forcément conseillé d’utiliser implode comme ça. L’ordre des paramètres est changé et cela peut créer des problèmes.

On peut même écrire ce code en une seule instruction :

echo implode(
    array_filter(
        array_map(
            fn($orig, $rec) => $orig !== $rec ? $rec[0] . $orig[0] : null,
            $originals,
            $recording
        )
    )
);

Le code ci-dessus n’est pas très lisible. Dans un vrai projet, il serait intéressant de le commenter et/ou de le découper pour mieux comprendre ce qu’il s’y passe. Mais dans le cadre d’un challenge, surtout lors d’un évènement comme Top Code, ce genre de fonctions sont de bons outils pour aller + vite et organiser le code différemment !

Pour aller + loin


Qui a codé ce superbe contenu ?

Keep learning

Other content to discover