Question

    

Cette question a déjà une réponse ici:

         

Désolé toutes ces questions stupides, j'ai été poussée dans la programmation Perl et je trouve qu'il est vraiment difficile de penser comme un programmeur Perl.

Question idiote pour aujourd'hui: Je charge un tuyau fichier délimité dans une table de hachage en utilisant le champ identifiant en tant que clé, comme ceci

#open file

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

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

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

quelques fois, cependant, quand j'ai besoin en fait la clé pour être le chemin parce que, pour une raison quelconque (et non, il ne peut pas être changé) l'identifiant est pas unique, donc j'eu la brillante idée que Je pourrais mettre tout en un sous-programme et passer le nom de la variable à utiliser comme clef, un peu comme ceci:

load_hash("path");

sub load_hash {
    my $key = shift;

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

mais dans perldb x $ {$ key} est toujours FNUD, bien que x $ {path} imprime la valeur dans le chemin de $.

Y at-il un moyen de faire ce que je suis en train de?

TIA

Était-ce utile?

La solution

Quelque chose comme ça?

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

Autres conseils

Vous essayez d'utiliser des « références symboliques ». Si vous avez un problème et vous pensez « hey, je vais résoudre ce avec des références symboliques » vous avez maintenant deux problèmes.

Tout d'abord, ils ne fonctionnent que sur globals. Vous avez déclaré $path comme lexical (visible uniquement dans le bloc où elle a été déclarée) et donc load_path ne peut pas le voir. Non, ne faites pas $path mondiale.

En second lieu, refs symbolique créer code spaghetti. Globals sont assez mauvais. Ils sont accessibles partout, à tout moment par quoi que ce soit. Avec une référence symbolique à un monde que vous ne pouvez pas voir même qui est en cours d'accès mondial. Cela ne permet pas de suivre ce qui pourrait changer quoi. Voilà pourquoi strict les désactive. Tournez le strict et laissez-le jusqu'à ce que vous savez quand vous devez désactiver.

Je ne suis pas tout à fait sûr de ce que vous essayez d'accomplir, mais il semble que ce soit bien.

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

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

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

Mais je serais probablement passer l'analyse syntaxique de la ligne en fonction et quitter l'affectation de hachage à la boucle principale. Analyse de la ligne est un morceau transparent de la logique et peut être totalement séparé de l'attribution de la ligne de la table de hachage de fichier. Un bon signe est que %hash ne doit pas être globale.

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;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top