Pregunta

Tengo una amplia gama de patrones que necesito emparejados. Cualquier forma de hacerlo, que no sea un bucle for ()? Im tratando de hacerlo en la forma intensiva menos CPU, ya que voy a estar haciendo docenas de estos cada minuto.

ejemplo del mundo real es, Im la construcción de un comprobador de estado del enlace, que comprobará enlaces a varios sitios de vídeo en línea, para asegurar que los vídeos están todavía viven. Cada dominio tiene varias palabras clave "muertas", si éstos se encuentran en el código HTML de una página, que significa que se elimina el archivo. Estos se almacenan en la matriz. Tengo que coincida con el contenido pf la matriz, en contra de la salida HTML de la página.

¿Fue útil?

Solución

En primer lugar, si, literalmente, sólo se está haciendo decenas cada minutos , entonces yo no se preocupe terriblemente sobre el rendimiento en este caso. Estos partidos son bastante rápido, y no creo que vas a tener un problema de rendimiento por iteración a través de la matriz de patrones y llamando preg_match separado de esta manera:

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

Puede en efecto combinar todos los patrones en una usando el operador or como algunas personas están sugiriendo, pero no acaba de dar una palmada juntos con un |. Esto romperá mal si alguno de sus patrones contienen el operador or.

Yo recomendaría al menos agrupar sus patrones usando paréntesis como:

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

Pero ... No estoy muy seguro de si esto termina siendo más rápido. Algo ha de bucle a través de ellos, si es el preg_match o PHP. Si tuviera que adivinar supongo que partidos individuales estarían cerca de lo más rápido y más fácil de leer y mantener.

Por último, si el rendimiento es lo que usted está buscando aquí, creo que la cosa más importante que hacer es sacar la no expresión coincide en un simple "cadena contiene" cheque. Me imagino que algunos de los cheques deben ser cheques de cadena sencilla como mirar para ver si "Este sitio está cerrado" está en la página.

Así que hacer esto:

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

y evitar el mayor número posible preg_match() probablemente va a ser su mejor ganancia. strpos() es un mucho más rápido que preg_match().

Otros consejos

// 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 los patrones no contienen muchos espacios en blanco, otra opción sería la de evitar las matrices y utilizar el modificador /x. Ahora su lista de expresiones regulares se vería así:

$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 el modificador /x, espacios en blanco se ignora por completo, excepto cuando en una clase de caracteres o precedido por una barra invertida. También se permiten comentarios como anteriormente.

Esto evitaría el bucle a través de la matriz.

Si usted está simplemente en busca de la presencia de una cadena en otra cadena, utilice strpos ya que es más rápido.

De lo contrario, usted podría iterar sobre el conjunto de patrones, llamando preg_match cada vez.

Si usted tiene un montón de patrones, lo que puede hacer es concatenar en una sola expresión regular y coincide. No hay necesidad de un bucle.

Lo que trata de hacer un str_replace() en el HTML que puedes conseguir utilizando la matriz y luego comprobar si el código HTML original es igual a la original? Esto sería muy rápido:

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

Se pueden combinar todos los patrones de la lista de expresiones regulares solo usando implosión () php function . A continuación, probar su cadena a la vez utilizando preg_match () php función.

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

Por supuesto que podría ser incluso menos código usando implosión en línea () en "if ()" condición en lugar de la variable $master_pattern.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top