2011-01-18 12 views
8

(Nota: no parece Título para despejar - si alguien puede reformular esto, estoy totalmente de acuerdo!)¿Utiliza la alternancia o la clase de caracteres para la coincidencia de caracteres individuales?

Teniendo en cuenta esta expresión regular: (.*_e\.txt), que coincide con algunos nombres de archivo, tengo que añadir algún otro carácter único sufijos además del e. ¿Debo elegir una clase de personaje o debería usar una alternancia para esto? (O ¿realmente importa ??)

Es decir, ¿cuál de los dos siguientes parece "mejor", y por qué:

a) (.*(e|f|x)\.txt) o

b) (.*[efx]\.txt)

+1

no le será difícil de medir __any__ rendimiento diferencia entre los dos. Deja de preocuparte y solo usa el más claro. – bobbogo

+1

@bobbogo: tenga en cuenta que la pregunta no era específicamente sobre el rendimiento, sino sobre "mejor" + por qué. –

+0

@Mrtin: Estoy completamente de acuerdo. Borrar el código es la prioridad aquí. – bobbogo

Respuesta

16

Uso [efx]: para eso están diseñadas exactamente las clases de caracteres: para hacer coincidir uno de los caracteres incluidos. Por lo tanto, también es la solución más fácil de leer y la más corta.

No sé si es más rápido, pero estaría muy sorprendido si no fuera así. Definitivamente no será más lento.

Mi razonamiento (sin haber escrito un motor de expresiones regulares, así que esto es pura conjetura):

La expresión regular símbolo [abc] se aplicará en un solo paso del motor de expresiones regulares: "es el siguiente carácter uno de a , b, o c? "

(a|b|c) sin embargo le dice al motor de expresiones regulares a

  • recordar la posición actual en la cadena para dar marcha atrás, si es necesario
  • comprobar si es posible hacer coincidir a. Si es así, éxito. Si no:
  • compruebe si es posible hacer coincidir b. Si es así, éxito. Si no es así:
  • cheque si es posible para que coincida con c. Si es así, éxito. Si no es así:
  • renunciar.
1

Con un solo carácter, tendrá una diferencia mínima que no importará. (a menos que esté haciendo MUCHOS de operaciones)

Sin embargo, para la legibilidad (y un ligero aumento en el rendimiento) debe utilizar el método de clase de caracteres.

Para abrir un paréntesis redondo ( hace que Perl comience a retroceder para esa posición actual, que, como no tiene más coincidencias para oponerse, realmente no necesita su expresión regular. Una clase de personaje no hará esto.

+1

Puede tener cierto control sobre el rastreo en un grupo usando '(?> ...)', el subgrupo independiente. De esta forma, el grupo en sí no será revisado una vez que se haya decidido alguna posibilidad. Sin embargo, es un poco complicado de usar. – tchrist

+0

@tchrist: mucho más simple es usar simplemente '(?: ...)' cada vez que no desee capturar el subgrupo. –

11

Aquí es un punto de referencia:

actualiza de acuerdo con comentario tchrist, la diferencia es más significativa

#!/usr/bin/perl 
use strict; 
use warnings; 
use 5.10.1; 
use Benchmark qw(:all); 

my @l; 
foreach(qw/b c d f g h j k l m n ñ p q r s t v w x z B C D F G H J K L M N ñ P Q R S T V W X Z/) { 
    push @l, "abc$_.txt"; 
} 

my $re1 = qr/^(.*(b|c|d|f|g|h|j|k|l|m|n|ñ|p|q|r|s|t|v|w|x|z)\.txt)$/; 
my $re2 = qr/^(.*[bcdfghjklmnñpqrstvwxz]\.txt)$/; 
my $cpt; 

my $count = -3; 
my $r = cmpthese($count, { 
    'alternation' => sub { 
     for(@l) { 
      $cpt++ if $_ =~ $re1; 
     } 
    }, 
    'class' => sub { 
     for(@l) { 
      $cpt++ if $_ =~ $re2; 
     } 
    } 
}); 

resultado:

   Rate alternation  class 
alternation 2855/s   --  -50% 
class  5677/s   99%   -- 
+2

Esa es una ilustración interesante, y creo útil. Aunque hay muchas cosas en las que no entra. Si modifica los datos de entrada, obtendrá un rendimiento diferente, al igual que usted, si varía los patrones. Por ejemplo, '[bcdfghjklmnñpqrstvwxz]' vs '(b | c | d | f | g | h | j | k | l | m | n | ñ | p | q | r | s | t | v | w | x | z) 'para las consonantes españolas es mucho más largo, y presumiblemente debe mostrar características de rendimiento diferentes. – tchrist

+0

Creo que deberías usar 'use utf8;' pragma porque tu '$ re1' y' $ re2' no coinciden; ;-) –

Cuestiones relacionadas