¿Cuál es la forma más inteligente de buscar a través de una matriz de cadenas de caracteres de una cadena coincidente en Perl?

Una advertencia, me gustaría que la búsqueda no distingue mayúsculas de minúsculas

así "aAa" sería en ("aaa","bbb")

  • cuántas veces te busque en la lista?
  • sólo será buscado una vez en realidad. tiempo de ejecución de la complejidad no es lo que estoy muy preocupada
  • no es que importe, o en cualquier manera relacionada con, pero si mantiene su matriz en un conjunto de claves hash (todos con el valor de ‘lo que sea’), usted puede averiguar si existe o no mucho más rápido aunque el caso de insensibilidad plantea un problema…ah, sí, y que ~~ smartmatch es lento como puede ser… de lo contrario, se adhieren con Éter bien documentada respuesta que demuestra que la respuesta más simple no siempre es la mejor respuesta, incluso si no es desde su punto de vista, la respuesta correcta.
InformationsquelleAutor Mike | 2010-05-27

7 Comentarios

  1. 29

    Supongo

    @foo = ("aAa", "bbb");
    @bar = grep(/^aaa/i, @foo);
    print join ",",@bar;

    haría el truco.

    • Tal vez: @bar = grep(/^aaa$/i, @foo); Ya que lo que escribió buscará todas las cadenas que comienzan con /aaa/i, por lo que también se encuentra el /aaaa/ y /aaaa+/.
    • Creo que sería más eficaz el uso de grep {lc $_ eq 'aaa'}, @foo evitando así la necesidad de RegEx de procesamiento.
    • Todo esto es cierto, y muy válida, dependiendo del caso de uso. Pero creo que los ejemplos dados por los OP son sólo ligeramente representante para su problema.
  2. 143

    Depende de lo que usted desea que la búsqueda a hacer:

    • si quieres encontrar todos los partidos, utilizar el built-in grep:

      my @matches = grep { /pattern/ } @list_of_strings;
    • si quieres encontrar el primer partido, uso first en Lista::Util:

      use List::Util 'first';  
      my $match = first { /pattern/ } @list_of_strings;
    • si quieres encontrar el recuento de todos los partidos, uso true en Lista::MoreUtils:

      use List::MoreUtils 'true';
      my $count = true { /pattern/ } @list_of_strings;
    • si quieres saber el índice de la primera coincidencia, uso first_index en Lista::MoreUtils:

      use List::MoreUtils 'first_index'; 
      my $index = first_index { /pattern/ } @list_of_strings;
    • si usted simplemente desea saber si no fue un partido, pero no importa de qué elemento fue o su valor de uso any en Lista::Util:

      use List::Util 1.33 'any';
      my $match_found = any { /pattern/ } @list_of_strings;

    Todos estos ejemplos que hagan cosas similares en su núcleo, pero sus implementaciones han sido muy optimizado para ser rápido, y será más rápido que cualquier puro-perl aplicación que usted puede escribir usted mismo con grep, mapa o un bucle for.


    Tenga en cuenta que el algoritmo para hacer el bucle es un tema aparte que la realización de los partidos individuales. Para que coincida con una cadena a mayúsculas-minúsculas, usted puede simplemente utilizar el i bandera en el patrón: /pattern/i. Definitivamente, usted debe leer a través de perldoc perlre si no lo ha hecho así.

    • Usted está asumiendo «partido» significa regex partido, pero el ejemplo dado es justo (no distingue mayúsculas de minúsculas) igualdad.
    • Me han sugerido perlretut para principiantes en lugar de perlre…
    • true es un poco una exageración de la OMI. Es más rápido que my $count = grep { /pattern/ } @list_of_strings; ?
    • o incluso perldoc perlrequick primero y luego más tarde perldoc perlreut
    • Zaid y Telémaco: perlretquick y perlretut ambos son mencionados específicamente en el primer párrafo en la descripción de perlre. Es el mejor para empezar, ya que se presenta al lector con una hoja de ruta sobre cómo proceder a lo largo de la ruta de aprendizaje. (a menos que usted está en un terminal con el síndrome del túnel carpiano o simplemente odio hacer clic en el ratón un tiempo extra).
  3. 29

    Perl 5.10+ contiene las ‘smart-match’ operador ~~, que devuelve true si un determinado elemento está contenida en una matriz o un hash, y falso si no (ver perlfaq4):

    Lo bueno es que también soporta expresiones regulares, lo que significa que tu no distingue mayúsculas de minúsculas requisito se puede tomar fácilmente la atención de:

    use strict;
    use warnings;
    use 5.010;
    
    my @array  = qw/aaa bbb/;
    my $wanted = 'aAa';
    
    say "'$wanted' matches!" if /$wanted/i ~~ @array;   # Prints "'aAa' matches!"
    • Por favor, ser conscientes de que la coincidencia inteligente característica es experimental (fuente)
  4. 6

    Si usted va a hacer muchos búsquedas de la matriz, Y coincidente siempre se define como la cadena de equivalencia, entonces usted puede normalizar los datos y el uso de un hash.

    my @strings = qw( aAa Bbb cCC DDD eee );
    
    my %string_lut;
    
    # Init via slice:
    @string_lut{ map uc, @strings } = ();
    
    # or use a for loop:
    #    for my $string ( @strings ) {
    #        $string_lut{ uc($string) } = undef;
    #    }
    
    
    #Look for a string:
    
    my $search = 'AAa';
    
    print "'$string' ", 
        ( exists $string_lut{ uc $string ? "IS" : "is NOT" ),
        " in the array\n";

    Permítanme subrayar que hacer un hash de búsqueda es bueno si usted está planeando en hacer muchas búsquedas en la matriz. También, sólo funcionará si la coincidencia significa que $foo eq $bar, u otros requisitos que pueden ser satisfechas a través de la normalización (como el caso de insensibilidad).

  5. 5
    #!/usr/bin/env perl
    
    use strict;
    use warnings;
    use Data::Dumper;
    
    my @bar = qw(aaa bbb);
    my @foo = grep {/aAa/i} @bar;
    
    print Dumper \@foo;
  6. 2

    Perl coincidencia con la cadena también puede ser utilizado para un simple sí/no.

    my @foo=("hello", "world", "foo", "bar");
    
    if ("@foo" =~ /\bhello\b/){
        print "found";
    }
    else{
        print "not found";
    }
    • Esto va a provocar falsos positivos en ciertas situaciones, por ejemplo, considere la posibilidad de my @foo = ( "hello world hello bar" );
    • Buena observación acerca de los falsos positivos. Estar consciente de eso, me parece agradable y simple, de una sola palabra de la prueba. Si es necesario, uno siempre puede agregar caracteres delimitadores el uso de join – por ejemplo el uso de \x01 iba a funcionar para la mayoría de texto-cadenas.
  7. 1

    Por sólo un boolean resultado del partido o para un recuento de las ocurrencias, puedes usar:

    use 5.014; use strict; use warnings;
    my @foo=('hello', 'world', 'foo', 'bar', 'hello world', 'HeLlo');
    my $patterns=join(',',@foo);
    for my $str (qw(quux world hello hEllO)) {
        my $count=map {m/^$str$/i} @foo;
        if ($count) {
            print "I found '$str' $count time(s) in '$patterns'\n";
        } else {
            print "I could not find '$str' in the pattern list\n"
        };
    }

    De salida:

    I could not find 'quux' in the pattern list
    I found 'world' 1 time(s) in 'hello,world,foo,bar,hello world,HeLlo'
    I found 'hello' 2 time(s) in 'hello,world,foo,bar,hello world,HeLlo'
    I found 'hEllO' 2 time(s) in 'hello,world,foo,bar,hello world,HeLlo'

    No requiere uso un módulo.

    Por supuesto, es menos «ampliable» y versátil como el código de arriba.

    Yo uso esto para el usuario interactivo respuestas coinciden con un conjunto predefinido de caso unsensitive respuestas.

Dejar respuesta

Please enter your comment!
Please enter your name here