Regex : condition ET...

Eléphant du PHP | 224 Messages

19 mai 2008, 09:41

Bonjour à tous :)

Voici un petit problème que je soumet volontiers à votre science des expressions régulières (ou rationnelles, je ne sais jamais trop :shock: )...

Je dispose d'une liste de strings. Je souhaiterai pouvoir choisir certains éléments de cette liste suivant un ou deux extraits de texte fournis.
Le choix des éléments si un des deux extraits est présent ne pose pas de soucis à priori, mais là où je coince, c'est la manière d'imaginer un masque capable de tester la présence des deux extraits de texte, quelque soit leur ordre d'apparition dans les éléments de la liste...

Bon, comme l'explication est un peu complexe, je sens que c'est le moment de montrer un peu de code ;) :
// Liste de strings d'où je dois isoler les éléments contenant deux extraits de texte :
$liste = array('undeuxtrois', 'troisdeux', 'deuxun', 'troisdeuxun');
// Les deux extraits de texte pour isoler les éléments de la liste qui les contiennent :
$extrait1 = 'un';
$extrait2 = 'trois';
// Ceci est une de mes nombreuses tentatives pour avoir le résultat souhaité :
$resultat = preg_grep("#(".$extrait1."|".$extrait2.").*(".$extrait1."|".$extrait2.")#", $liste);
// Visualisation du résultat :
var_export($resultat); // array ( 0 => 'undeuxtrois', 3 => 'troisdeuxun', ) 
Ok, le masque du "preg_grep" que j'utilise dans ce code semble bien fonctionner, en tout cas il me retourne une liste d'éléments contenant les deux extraits recherchés...

Seulement, je me dis qu'il y a sûrement une syntaxe de masque bien plus simple à utiliser pour trouver les éléments de la liste qui contiennent l'extrait 1 ET l'extrait 2, quelque soit leur ordre d'apparition dans le texte, mais, malgré mes multiples tentatives, je ne suis pas arrivé à la trouver...

Du coup, je me demande si quelqu'un avait une petite idée de la manière de simplifier ce masque tout en obtenant les résultats escomptés ? :?: :shock:

Merci de vos lumières... à+ :)
Fredo d;o)
"Un pas à la fois me suffit..." (Gandhi)

ViPHP
ViPHP | 4039 Messages

19 mai 2008, 10:03

Fait appel à la force des expressions régulières.. le regex, ce n'est pas de la programmation (sauf du côté obscur). Du coup, il faut s'adapter, saisir les limites des expressions régulières, pour comprendre ce qui est faisable.

Il te faut donc "deux" et "trois".

Un simple regex comme celui-ci valide tout ce qui contient 2 et 3:

Code : Tout sélectionner

deux.*trois
Mais, quid si 3 puis 2 ? alors, vient "l'alternation" (oui, ça fait "ou", mais c'est nocif de le considérér comme tel)
deux.*trois|trois.*deux
Quid du ".*" ?

Ben, le point valide tout, et on le répète de 0 à l'infini. Jusqu'au dernier "trois" de la chaîne.

Maintenant, si c'est vraiment la présence de simples mots que tu comptes vérifier, un simple strpos() sera bien plus rapide à mon avis.
Mais qu'importe. (je suis ici - dernier petit projet)
Berze going social.

Eléphant du PHP | 224 Messages

19 mai 2008, 10:48

Re...
deux.*trois|trois.*deux
Wouw, alors là, génial, ça marche super bien et ça a l'air même plus rapide que ma première syntaxe, merci very beaucoup much ! :pouce:
Maintenant, si c'est vraiment la présence de simples mots que tu comptes vérifier, un simple strpos() sera bien plus rapide à mon avis.


Oui, en effet, j'ai d'ailleurs commencé par utiliser le "strpos()" dans une boucle, et c'est une solution plutôt assez véloce, mais je voulais utiliser la fonction "preg_grep()" dans le cadre du script sur lequel je bosse en ce moment, juste histoire d'avoir un peu de cohérence avec les autres traitements...

Bref, ta syntaxe, même si elle semble toujours un peu moins rapide que la boucle avec le "strpos()", la différence n'est plus assez significative comme pour l'écarter, ce qui était plutôt le cas avec ma première syntaxe...

Voilô... encore merci pour ton aide, précieuse sur ce coup ! ;)

à+ :)

[Edit]
Bon, je mets "Résolu", même si je reste attentif à d'autres pistes ou propositions... des volontaires ? :shock: :D
[/Edit]
Fredo d;o)
"Un pas à la fois me suffit..." (Gandhi)