¿Cómo puedo utilizar el valor de una variable como un nombre de variable Perl? [duplicar]

StackOverflow https://stackoverflow.com/questions/1726363

Pregunta

    

Esta pregunta ya tiene una respuesta aquí:

         

Lo siento por todas estas preguntas tontas, he estado inmerso en la programación Perl y se me hace muy difícil pensar como un programador de Perl.

Pregunta tonta para hoy: Me carga un archivo delimitado tubo en un hash utilizando el campo id como la clave, al igual que

#open file

my %hash;
while (<MY_FILE>) {
    chomp;

    my ($id, $path, $date) = split /\|/;

    $hash{$id} = {
        "path" => $path,
        "date" => $date
    };
}

Hay un par de veces, sin embargo, cuando realmente se necesita la clave para ser el camino, ya que, por cualquier razón (y no, no se puede cambiar) el identificador no es única, por lo que tuvieron la brillante idea de que podría ponerlo todo en una subrutina y pasar el nombre de la variable que se utiliza como clave para que, de manera un poco como:

load_hash("path");

sub load_hash {
    my $key = shift;

    #do stuff, and then in while loop
    $hash{${$key}} = #and so on
}

pero en perldb x $ {} $ clave es siempre undef, aunque x $ {ruta} imprime el valor de $ ruta.

¿Hay alguna manera de hacer lo que estoy tratando de?

TIA

¿Fue útil?

Solución

Algo como esto?

use Carp 'confess';

sub load_hash {
    my $key = shift;

    # ...

    while (...) {
        # ...
        my %line;  # important that this is *inside* the loop
        @line{qw (id path date)} = split /\|/;
        confess "BUG: unknown key '$key'"  unless exists $line{$key};  # error checking
        $hash{$line{$key}} = \%line;
        delete $line{$key};  # assuming you don't want the key value duplicated
    }
}

Otros consejos

Usted está tratando de utilizar "referencias simbólicas". Si usted tiene un problema y piensa "bueno, voy a resolver esto con referencias simbólicas" Ahora tiene dos problemas.

En primer lugar, que sólo funciona en variables globales. Usted ha declarado $path como un léxico (sólo visible en el bloque que fue declarado) y por lo tanto load_path no puede verlo. No, no hacen $path global.

En segundo lugar, referencias simbólicas crean código espagueti. Globales son bastante malas. Se puede acceder en cualquier momento y por cualquier cosa. Con una referencia simbólica a un mundial ni siquiera se puede ver cuál mundial se está accediendo. Esto hace que sea imposible realizar un seguimiento de lo que podría cambiar lo. Esta es la razón por strict los desactiva. Encienda strict y dejar actuar hasta que no sepa cuándo debe apagarlo.

No estoy del todo seguro de lo que estamos tratando de lograr, pero parece que esto está muy bien.

my %hash;
while (<MY_FILE>) {
    chomp;

    my ($id, $path, $date) = split /\|/;

    $hash{$path} = {
        "path" => $path,
        "date" => $date
    };
}

Pero probablemente me muevo el análisis de la línea en una función y dejar la asignación de hash al bucle principal. Analizar la línea es una clara parte de la lógica y puede ser totalmente separado de la asignación de la línea hasta el hash del archivo. Una buena señal es que %hash no tiene que ser global.

my %hash;
while (<MY_FILE>) {
    my $line = parse_line($_);

    my $id = $line->{path};
    $hash{$id} = $line;
}


my @fields = qw(id path date);
sub parse_line {
    my $line = shift;
    chomp $line;

    my %data;
    # This is assigning to a hash slice.  Look it up, its handy.
    @data{@fields} = split m{\|}, $line;

    return \%data;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top