1
votes

Regex pour obtenir des chaînes qui ne contiennent que les mots de la liste de modèles?

Considérez les éléments de tableau suivants

1.benclinton  
2.clintonharry  
3.harryben

Supposons que la liste de modèles est ben, harry, clinton , alors le résultat que je devrais obtenir est

 1.benclinton
 2.clintonharry
 3.harryben
 4.benwill
 5.jasonsmith
 6.smithclinton

Donc, essentiellement le résultat doit contenir des chaînes qui ne contiennent que les mots qui sont dans la liste des modèles. L'ordre n'est pas important

De plus, chaque chaîne n'aura pas plus de deux mots. c'est-à-dire que bensmith ne sera jamais un cas.

Puisque toutes mes chaînes sont dans un tableau, j'ai pensé à utiliser preg_grep en php pour faire cela, mais je suis frappé de cadrer correctement le regex pour cela.

quelle regex peut y parvenir? Existe-t-il un autre moyen efficace en dehors de la correspondance de regex qui fera le travail?

Merci d'avance!


0 commentaires

3 Réponses :


0
votes

Il semble que vous vouliez faire correspondre les éléments du tableau qui sont des combinaisons exactes de deux mots-clés. Pour une approche regex, nous pouvons essayer de prendre le produit croisé du vecteur de keyords, puis générer une alternance. Ensuite, nous pouvons utiliser preg_grep contre votre tableau d'entrée pour trouver tous les éléments correspondants.

(benben|benharry|benclinton|harryben|harryharry|harryclinton|clintonben|
    clintonharry|clintonclinton)

Voici l'alternance regex générée par le script ci-dessus:

XXX


1 commentaires

Merci. Existe-t-il un moyen sans utiliser la boucle for?



0
votes

Sans Regex.Do avec array_filter et strpos

  1. Filtrer le tableau avec le deuxième tableau correspondant respecté dont le nombre est supérieur à 1

Sandbox

<?php
$a = ['benclinton','clintonharry','harryben','benwill','jasonsmith','smithclinton'];
$a2 = ['ben','clinton','harry'];
$res = array_filter($a,function($str="") use($a2){
    $r =array_filter($a2,function($a2str) use($str){
        return strpos($str,$a2str) !== FALSE;
    });
    return count($r) > 1;
});
print_r($res);
?>


0 commentaires

3
votes

Quelque chose comme ceci

$matches = preg_grep('/('.implode('|',array_map(function($name){return preg_quote($name,'/');},$names)).')(?1)/', $names_list);

Sortie

Array
(
    [0] => benclinton
    [1] => clintonharry
    [2] => harryben
)

Sandbox

Cela nécessite qu'au moins deux des noms (même le même 2x) correspondent. Mais c'est un peu donné dans ce cas ou tout correspondrait.

Si vous voulez être très prudent, si les $ names peuvent contenir quelque chose d'important pour l'expression régulière, comme + , * , \ etc. vous pouvez ajouter ceci

$names_list = ['benclinton','clintonharry','harryben','benwill','jasonsmith','smithclinton'];
$names = ['ben','harry','clinton'];  

$matches = preg_grep('/('.implode('|',$names).')(?1)/', $names_list);
//-  /(ben|harry|clinton)(?1)/  -- (?1) = recurse capture group 1 

print_r($matches);


3 commentaires

Cela correspond à benbenclinton . Je ne sais pas si l'OP s'attend à ce qu'un terme soit une correspondance exacte de deux sous-chaînes.


@TimBiegeleisen - tout comme le vôtre. Sandbox


Je peux faire la même chose avec ^ et $ Sandbox - il suffit de dire. :-)