Question

J'ai une gamme complète de modèles que j'ai besoin appareillés. De toute façon de le faire, autre qu'une boucle for ()? Im essayant de le faire de la manière intensive moins de CPU, puisque je vais faire des dizaines de ces chaque minute.

exemple du monde réel est, Im la construction d'un état de vérificateur de liens, qui va vérifier des liens vers différents sites de vidéo en ligne, pour faire en sorte que les vidéos sont vivent encore. Chaque domaine a plusieurs mots-clés « morts », si ceux-ci se trouvent dans le code HTML d'une page, cela signifie que le fichier a été supprimé. Ceux-ci sont stockés dans le tableau. Je dois correspondre au contenu du tableau PF, contre la sortie HTML de la page.

Était-ce utile?

La solution

Tout d'abord, si vous ne faites que des dizaines tous minute , alors je ne vous inquiétez pas terriblement sur les performances dans ce cas. Ces résultats sont assez rapides, et je ne pense pas que vous allez avoir un problème de performance par itérer votre tableau de modèles et d'appeler preg_match séparément comme ceci:

$matches = false;
foreach ($pattern_array as $pattern)
{
  if (preg_match($pattern, $page))
  {
    $matches = true;
  } 
}

Vous pouvez en effet combiner tous les modèles en un seul avec l'opérateur or comme certains proposent, mais ne vous contentez pas de les frapper avec un |. Ceci brisera mal si l'un de vos modèles contiennent ou l'opérateur.

Je recommande au moins grouper vos modèles en utilisant entre parenthèses comme:

foreach ($patterns as $pattern)
{
  $grouped_patterns[] = "(" . $pattern . ")";
}
$master_pattern = implode($grouped_patterns, "|");

Mais ... Je ne suis pas sûr si cela finit par être plus rapide. Quelque chose en boucle à travers eux, que ce soit le preg_match ou PHP. Si je devais deviner je suppose que les matchs individuels seraient proches de aussi vite et plus facile à lire et à maintenir.

Enfin, si la performance est ce que vous cherchez ici, je pense que la chose la plus importante à faire est de tirer le non regex correspond à une simple « chaîne contient » chèque. Je suppose que certains de vos chèques doivent être des contrôles à cordes simples comme regarder pour voir si « ce site est fermé » est sur la page.

faire ceci:

foreach ($strings_to_match as $string_to_match)
{
  if (strpos($page, $string_to_match) !== false))
  {
    // etc.
    break;
  }
}
foreach ($pattern_array as $pattern)
{
  if (preg_match($pattern, $page))
  {
    // etc.
    break;
  } 
}

et en évitant autant que possible preg_match() va probablement être votre meilleur gain. strpos() est un beaucoup plus vite que preg_match().

Autres conseils

// assuming you have something like this
$patterns = array('a','b','\w');

// converts the array into a regex friendly or list
$patterns_flattened = implode('|', $patterns);

if ( preg_match('/'. $patterns_flattened .'/', $string, $matches) )
{
}

// PS: that's off the top of my head, I didn't check it in a code editor

Si vos modèles ne contiennent pas beaucoup les espaces blancs, une autre option serait d'éviter les tableaux et utiliser le modificateur de /x. Maintenant, votre liste d'expressions régulières ressemblerait à ceci:

$regex = "/
pattern1|   # search for occurences of 'pattern1'
pa..ern2|   # wildcard search for occurences of 'pa..ern2'
pat[ ]tern| # search for 'pat tern', whitespace is escaped
mypat       # Note that the last pattern does NOT have a pipe char
/x";

Avec le modificateur /x, des espaces est complètement ignorée, sauf si dans une classe de caractère ou précédée d'une barre oblique inverse. Des commentaires comme ci-dessus sont également autorisés.

Cela permettrait d'éviter la boucle à travers le réseau.

Si vous êtes simplement rechercher la présence d'une chaîne dans une autre chaîne, utilisez strpos comme il est plus rapide.

Dans le cas contraire, vous pouvez simplement itérer sur le tableau de motifs, appelant preg_match chaque fois.

Si vous avez un tas de modèles, ce que vous pouvez faire est de les concaténer en une seule expression régulière et qui correspond. Pas besoin d'une boucle.

Qu'en est-il de faire une str_replace() sur le code HTML que vous obtenez en utilisant votre tableau et ensuite vérifier si le code HTML d'origine est égal à l'original? Ce serait très rapide:

 $sites = array(
      'you_tube' => array('dead', 'moved'),
      ...
 );
 foreach ($sites as $site => $deadArray) {
     // get $html
     if ($html == str_replace($deadArray, '', $html)) { 
         // video is live
     }
 }

Vous pouvez combiner tous les modèles de la liste à l'expression régulière unique en utilisant implode () fonction php. Ensuite, testez votre chaîne à la fois en utilisant preg_match () fonction php.

$patterns = array(
  'abc',
  '\d+h',
  '[abc]{6,8}\-\s*[xyz]{6,8}',
);

$master_pattern = '/(' . implode($patterns, ')|(') . ')/'

if(preg_match($master_pattern, $string_to_check))
{
  //do something
}

Bien sûr, il pourrait y avoir encore moins de code en utilisant inline implode () dans "if ()" état au lieu de la variable $master_pattern.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top