Pergunta

Esta questão já tem uma resposta aqui:

Desculpe sobre todas essas perguntas tolas, eu fui arrastado para a programação Perl e estou achando muito difícil pensar como um programador de Perl.

Pergunta boba para hoje: Eu carregar um arquivo delimitado tubulação em um hash usando o campo id como a chave, como assim

#open file

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

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

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

Há algumas vezes, no entanto, quando eu realmente preciso a chave para ser o caminho, porque, por qualquer razão (e não, ele não pode ser alterado) o id não é única, então eu tive a brilhante ideia de que Eu poderia colocar tudo em uma sub-rotina e passar o nome da variável para usar como a chave para ela, tipo assim:

load_hash("path");

sub load_hash {
    my $key = shift;

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

mas em perldb x {$ key} $ é sempre undef, embora x $ {path} imprime o valor em $ path.

Existe alguma maneira de fazer o que eu estou tentando?

TIA

Foi útil?

Solução

Algo como isso?

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

Outras dicas

Você está tentando usar "referências simbólicas". Se você tem um problema e você pensa "hey, eu vou resolver isso com referências simbólicas" agora você tem dois problemas.

Em primeiro lugar, eles só funcionam em globals. Você declarou $path como lexical (visível apenas no bloco que foi declarado) e, assim, LOAD_PATH não pode vê-lo. Não, não faça $path global.

Em segundo lugar, refs simbólicos criar código espaguete. Globals são ruins o suficiente. Eles podem ser acessados ??em qualquer lugar, a qualquer hora por qualquer coisa. Com uma referência simbólica a um global, você não pode sequer ver qual global está sendo acessado. Isso torna impossível para acompanhar o que pode mudar o que. É por isso que strict transforma-las. Ligue strict e deixá-lo até que você sabe quando você deve desligá-lo.

Eu não sou inteiramente certo o que você está tentando realizar, mas parece que isso é bom.

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

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

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

Mas eu provavelmente mover a análise da linha em uma função e deixar a atribuição de hash para o loop principal. Analisando a linha é um pedaço clara da lógica e pode ser totalmente separado de atribuir a linha para o hash do arquivo. Um bom sinal é que %hash não tem 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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top