Domanda

Ho una gamma completa di modelli che ho bisogno abbinato. Un modo per farlo, diverso da un ciclo for ()? Im cercando di farlo nel modo intensivo minimo della CPU, dal momento che cercherò di fare decine di questi ogni minuto.

esempio del mondo reale è, Im la costruzione di un ispettore stato del collegamento, che controllerà i link ai vari siti di video online, per assicurare che i video sono ancora vive. Ogni dominio ha diversi "parole chiave morti", se questi si trovano nel codice HTML di una pagina, che significa che il file è stato eliminato. Questi sono memorizzati nella matrice. Ho bisogno di abbinare il contenuto pf matrice, contro l'output HTML della pagina.

È stato utile?

Soluzione

Prima di tutto, se si sta solo facendo letteralmente decine ogni minuto , quindi vorrei non preoccupatevi terribilmente per le prestazioni in questo caso. Queste partite sono piuttosto veloce, e non credo che si sta andando ad avere un problema di prestazioni scorrendo l'array modelli e chiamando preg_match separatamente in questo modo:

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

È possibile infatti combinare tutti i modelli in una sola utilizzando l'operatore or come alcune persone stanno suggerendo, ma non solo loro schiaffo insieme ad un |. Questo si romperà male se uno dei tuoi modelli di contengono l'operatore OR.

mi sento di raccomandare almeno raggruppare i vostri modelli utilizzando parentesi come:

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

Ma ... io non sono davvero sicuro se questo finisce per essere più veloce. Qualcosa ha a ciclo attraverso di loro, se è il preg_match o PHP. Se dovessi indovinare direi che le singole partite sarebbe vicino alla più veloce e più facile da leggere e gestire.

Infine, se le prestazioni è quello che stai cercando qui, penso che la cosa più importante da fare è tirare fuori il non regex trova in un semplice "stringa contiene" assegno. Immagino che alcuni dei vostri controlli devono essere semplici controlli di stringa come guardare per vedere se "Questo sito è chiuso" è sulla pagina.

In questo modo:

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;
  } 
}

ed evitare il maggior numero preg_match() possibile è destinata probabilmente ad essere il vostro migliore guadagno. strpos() è un molto più veloce di preg_match().

Altri suggerimenti

// 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

Se i modelli non contengono molti spazi bianchi, un'altra opzione potrebbe essere quella di rifuggire gli array e utilizzare il modificatore /x. Ora il vostro elenco di espressioni regolari sarebbe simile a questa:

$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";

Con il modificatore /x, spazi è completamente ignorato, tranne quando in una classe di caratteri o preceduto da una barra rovesciata. Commenti come sopra sono anche permesso.

Questo eviterebbe la cascata della matrice.

Se siete semplicemente alla ricerca per la presenza di una stringa in un'altra stringa, utilizzare strpos in quanto è più veloce.

In caso contrario, si può solo scorrere sopra la gamma di modelli, chiamando preg_match ogni volta.

Se hai un sacco di modelli, che cosa si può fare è concatenare in una singola espressione regolare e corrisponde a quello. Non c'è bisogno di un ciclo.

Che cosa di fare un str_replace() sul HTML si ottiene utilizzando la matrice e quindi verificare se il codice HTML originale è uguale a quello originale? Questo sarebbe molto veloce:

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

È possibile combinare tutti i modelli dalla lista per singola espressione regolare utilizzando implode () funzione php . Quindi verificare la stringa in una sola volta utilizzando preg_match () funzione 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
}

Naturalmente ci potrebbe essere anche meno codice utilizzando implode () ancorato in "if ()" condizione anziché variabile $master_pattern.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top