Tengo un script en Perl que es contar el número de apariciones de varias cadenas de caracteres en un archivo de texto. Quiero ser capaz de comprobar si una determinada cadena todavía no es una clave en el hash. Hay una mejor manera de hacer todo esto?

Aquí es lo que yo estoy haciendo:

foreach $line (@lines){
    if(($line =~ m|my regex|) )
    {
        $string = $1;
        if ($string is not a key in %strings) # "strings" is an associative array
        {
            $strings{$string} = 1;
        }
        else
        {
            $n = ($strings{$string});
            $strings{$string} = $n +1;
        }
    }
}
  • La pregunta es, ¿por qué siquiera se molesta con eso? Si no existe, entonces $n será undef. Undef el valor numérico es 0, por lo que $n+1=1. No hay necesidad de comprobar si existe en el hash, para empezar.
InformationsquelleAutor | 2009-06-16

5 Comentarios

  1. 111

    Creo que para comprobar si una clave existe en un hash que acaba de hacer

    if (exists $strings{$string}) {
        ...
    } else {
        ...
    }
    • Ser conscientes de que perl se autovivicate ningún intermediario claves que no existen en un multidimensionales hash con el fin de «verificar» si la clave que tu buscas en la última hash existe. No es un problema con una simple hash como por ejemplo esta, pero .. mi %de prueba = (); imprimir «de la barra de» if(exists $prueba{‘foo’}{‘bar’}); # perl sólo autovivified los foo clave para buscar de la barra de impresión «foo existe hoy en día y usted tal vez no esperaba eso!» if(exists $prueba{‘foo’});
  2. 10

    Me daba consejos en contra del uso de if ($hash{$key}) como no va a hacer lo que usted espera si la clave existe, pero su valor es cero o vacío.

    • Aquellos ciertas circunstancias son sólo para anidada claves. Para este problema, existe es la respuesta. No utilice existe para anidada claves en una sola toma.
    • Downvote todavía es un poco duro a pesar de que la advertencia no es invalidado por la simplicidad de la secuencia de comandos en esta pregunta. El punto más importante es la cuestión de usar la si($hash{$key}) con ni definido ni existe: el «cero pero el verdadero problema».
    • El «cero pero cierto» cosa merece un upvote. Pero lo que usted dijo acerca de autovivification simplemente está mal y merece un downvote.
    • La advertencia aquí es cierto en un camino – el autovivification que podría suceder, aunque no con el ejemplo – pero la propuesta de respuesta definidos() tiene exactamente el mismo problema, así que esto no es ninguna solución en absoluto.
    • De hecho – un comentario justo. Era demasiado temprano en la mañana, cuando me escribió que contestar, así que he reescrito ahora estoy suficientemente con cafeína.
    • Upvoted ahora. Es una advertencia justa ahora la autovivification poco se ha eliminado.

  3. 9

    Bien, todo tu código puede ser limitado a:

    foreach $line (@lines){
            $strings{$1}++ if $line =~ m|my regex|;
    }

    Si el valor no está allí, ++ operador asumirá a 0 y, a continuación, se incremente a 1). Si es que ya existe – es simplemente ser incrementado.

    • Mientras que su respuesta es verdadera, se hace responder a la pregunta acerca de hashes.
  4. 6

    Supongo que este código debe responder a su pregunta:

    use strict;
    use warnings;
    
    my @keys = qw/one two three two/;
    my %hash;
    for my $key (@keys)
    {
        $hash{$key}++;
    }
    
    for my $key (keys %hash)
    {
       print "$key: ", $hash{$key}, "\n";
    }

    De salida:

    three: 1
    one: 1
    two: 2

    La iteración puede ser simplificada a:

    $hash{$_}++ for (@keys);

    (Ver $_ en perlvar.) Y usted puede incluso escribir algo como esto:

    $hash{$_}++ or print "Found new value: $_.\n" for (@keys);

    Que los informes de cada clave de la primera vez que se encontraron.

    • Sí, la cosa es que no voy a saber de antemano lo que las llaves.
    • Sí, no es necesario para comprobar la presencia de la clave para este propósito. Usted puede simplemente decir $cadenas{$1}++ . Si la clave no está ahí, será añadido con undef como valor, el cual ++ se interpreta como 0 para usted.
    • Seguro. El punto es que usted puede cambiar todo el cuerpo de su ciclo (en el si) con $cadenas{$1}++.
    • (Lo siento, metido hasta el flujo de ‘edición’ mi comentario 🙂
  5. -2

    Se puede ir con:

    if(!$strings{$string}) ....
    • Esto sólo funciona si todas las teclas tienen valores que no son falsas. En general, esa es una mala suposición. Utilice existe(), que está especialmente diseñado sólo para esto.
    • de foy – Ah, ja. Yo sabía que no me han contestado 🙂
    • Además, su construcción crea una entrada en el hash. Para la pregunta en cuestión este es probablemente irrelevante, pero para otros casos puede ser relevante. Utilizando existe() también evita este problema y no se crea una entrada en el hash.
    • No, No es así. Trate de perl -le ‘print «ok» si !$un{hola}; print teclas de %a’
    • Sólo en anidados hashes ¿tiene usted un problema intermedio, accesos a crear las entradas. Así $a{$x}{$y} creará $a{$x}, independientemente de si usted utiliza exists o cualquier otro enfoque.

Dejar respuesta

Please enter your comment!
Please enter your name here