Top Code 2024, les challenges sont de nouveau disponibles dans les boards pour les participant(e)s => Boards

Comment parser des données en PHP ?

4 techniques de parsing en PHP : substr, explode, sscanf et des regex !

→ Corrigé du Challenge : Bulma et la Capsule Corp.

Comprendre et maîtriser le parsing en PHP

Le parsing (ou analyse syntaxique) est un terme qui revient souvent dans le monde de la programmation. Il s’agit de décomposer et d’interpréter une séquence d’entrée (très souvent du texte) en des éléments compréhensibles pour la suite du programme.

C’est important de maitriser le parsing car les sources de données disponibles actuellement (bases de données, APIs, fichiers divers, scrapping, etc.) présentent des formats très variés. Savoir extraire, transformer, et structurer ces données est donc crucial.

PHP possède plusieurs techniques de parsing. En connaissant et maitrisant ces techniques, tu seras mieux équipé pour optimiser ton code face à cette problématique. Ce corrigé te présente 4 techniques de parsing.

Au programme :

Introduction

Dans le challenge DBZ_2, il faut parser ce type de chaîne de caractères :

RNBOAPHELSK-182

Pour en sortir 2 informations :

  • Le code, RNBOAPHELSK (longueur variable)
  • Le poids, 182

Il faut donc parser la chaîne de caractères pour récupérer ces 2 valeurs.

Pour les exemples ci-dessous, on considère que RNBOAPHELSK-182 est stocké dans $object.

substr en PHP

Cette fonction permet de récupérer la portion d’une chaîne de caractères.

Dans ce cas précis, pour récupérer le code, il faut que je connaisse la longueur de celui-ci. Une possibilité est de déterminer la position du tiret « – » dans la chaîne principale.

$position = strpos($object, '-');
$code = substr($object, 0, $position);
// Et donc :
$weight = substr($object, $position + 1, 3);

Le code ci-dessus peut être optimisé :

$code = substr($object,
            0,
            strpos($object, '-')
);
$weight = substr($object, -3);

Je n’ai finalement plus besoin de $position et je passe donc strpos dans l’appel à substr.

Pour récupérer la fin d’une chaîne de caractères, je peux utiliser une valeur négative. Ici je récupère donc les 3 derniers caractères de $object.

La doc complète : substr.

explode en PHP

Cette fonction permet de découper une chaine de caractères, selon un séparateur. Ce séparateur peut être 1 seul caractère ou 1 chaine de caractères plus longue.

Ici, le tiret est le séparateur.

$informationss = explode('-', $object);
$code = $informations[0];
$weight = $informations[1];

explode retourne un tableau avec les différentes portions de la chaîne de caractères principale. Ici il y a 1 seul tiret, donc 2 portions, une avant (0, le code), une après (1, le poids). Le code ci-dessus peut être optimisé avec une double affectation :

[$code, $weight] = explode('-', $object);

La doc complète : explode.

sscanf en PHP

Cette fonction est « l’inverse » de la fonction sprintf.

sprintf permet d’intégrer les valeurs de variables dans une chaine de caractères, à la manière d’un publipostage.

$fruit = 'pomme';
echo sprintf('Je mange une %s', $fruit);
// Affiche : Je mange une pomme

s représente une chaîne de caractères.

sscanf va donc se comporter à l’inverse. C’est-à-dire que l’on va pouvoir définir le format d’une chaîne et en récupérer les différentes valeurs. Le problème avec notre challenge, c’est que scan utilise les espaces comme séparateur. Ce qui veut dire que ce code ne fonctionne pas comme souhaité :

[$code, $vert] = sscanf($object, '%s-%d');

Il n’y a pas d’espace, donc $code va récupérer toute la chaîne, et il n’y aura rien dans $weight.

On peut donc remplacer le tiret pour commencer :

$object = str_replace('-', ' ', $object);
[$code, $weight] = sscanf($object, '%s %d');

Cette fois-ci ça fonctionne 🙂

La doc complète : sscanf et sprintf.

Expressions régulières en PHP

Ah ces bonnes vieilles regex ! Analysons $object, il contient :

  • Un code, composé d’un nombre inconnu de lettres majuscules
  • Un poids, composé de 3 chiffres

On peut donc écrire ces 2 récupérations, par des expressions régulières :

preg_match('/[A-Z]+/', $object, $code);
$code = $code[0];

preg_match('/[0-9]{3}/', $object, $weight);
$weight = $weight[0];

Attention au fonctionnement de cette fonction, elle retourne le nombre de correspondances trouvées dans la chaîne de caractères principale. Et les correspondances sont assignées par référence, dans un tableau. Ici je sais que je ne vais avoir qu’une seule correspondance. Je récupère donc la valeur souhaitée avec [0].

La doc complète : preg_match

2 utilitaires pour rédiger ou tester des regex : phpliveregex et regex101.

Corrigé du challenge

Revenons au challenge !

Je choisis d’utiliser ici explode.

$total = 0;
foreach ($objects as $object) {

	[$code, $weight] = explode('-', $object);

	$codeMini = substr($code, 0, 2) . substr($code, -2) . '-' . floor($weight / 10);

	if (in_array($codeMini, $capsules)) {
		$total += $weight;
	}
}

J’initialise $total à 0, puisque je cherche une somme.

Je parcours tous mes objects (attention, le challenge fournit une clé « objets » et non « objects », mais on va corriger ça :p )

J’utilise donc explode pour extraire le code et le poids.

Je définis le codeMini. J’utilise ici substr puisque ce sont bien des portions de $code que je cherche. J’utilise d’ailleurs « -2 » pour les 2 derniers caractères.

Si $codeMini est dans $capsules, j’incrémente $total avec $weight.

Version fun condensée :

$total = 0;
foreach ($objects as $object) {
	$total += (in_array(
			substr(explode('-', $object)[0], 0, 2) . 
			substr(explode('-', $object)[0], -2) . '-' . 
			floor(explode('-', $object)[1] / 10)
		, $capsules)
	) ? explode('-', $object)[1] : 0;
}

On remplace le if par un ternaire. Soit j’ajoute le poids, soit j’ajoute zéro.

Et je récupère à la volée les résultats de explode. Ici c’est pour le fun puisque mon explode est utilisé plusieurs fois, j’ai plutot intérêt à stocker le résultat. Mais cette syntaxe est possible.

On met en application le parsing en PHP ?

Il existe encore d’autres techniques, mais garde à l’esprit que maîtriser différentes techniques de parsing te permet d’aborder avec flexibilité et efficacité le vaste monde des données et de leur traitement !

Voici 3 challenges qui démarrent avec des données à parser :


Qui a codé ce superbe contenu ?

Keep learning

Autres contenus à découvrir


Ta newsletter chaque mois

Corrigés, challenges, actualités, veille technique... aucun spam.