2010-01-03 8 views
1

C'est l'extrait de code, je travaille avec:Comment puis-je référencer un hachage Perl dans un tableau dans un hachage?

my %photo_details = (
'black_cat' => (
    ('size' => '1600x1200', 'position' => -25), 
    ('size' => '1280x1024', 'position' => 25), 
    ('size' => '800x600', 'position' => 0), 
), 
'race_car' => (
    ('size' => '1600x1200', 'position' => 10), 
    ('size' => '800x600', 'position' => 5), 
), 
); 

my $photo = 'black_cat'; 

foreach my $photo_detail ($photo_details{$photo}) 
{ 
my $size  = $photo_detail{'size'}; 
my $position = $photo_detail{'position'}; 

print ("size = $size, position = $position\n"); 
} 

Ce que je me attends à obtenir est:

size = 1600x1200, position = -25

size = 1280x1024, position = 25

size = 800x600, position = 0

Ce que je n'est:

Use of uninitialized value $size in concatenation (.) or string at C:\Test.pl line 23.

Use of uninitialized value $position in concatenation (.) or string at C:\Test.pl line 23.

size = , position =

Foreach est clairement faux car non seulement il n'y a pas de valeurs pour la taille $ et la position $, mais seulement une boucle au lieu de trois. J'ai essayé toutes sortes de variantes de préfixes variables et n'en ai trouvé aucun qui fonctionne.

Qu'est-ce que je fais mal?

Répondre

12

Voici un code mis à jour, avec une explication ci-dessous:

#!/usr/bin/perl 

use strict; 
use warnings; 

use Data::Dumper; 

my %photo_details = (
    'black_cat' => [ 
     {'size' => '1600x1200', 'position' => -25}, 
     {'size' => '1280x1024', 'position' => 25}, 
     {'size' => '800x600', 'position' => 0}, 
    ], 
    'race_car' => [ 
     {'size' => '1600x1200', 'position' => 10}, 
     {'size' => '800x600', 'position' => 5}, 
    ], 
); 


print Dumper(%photo_details); 
foreach my $name (keys %photo_details) { 
    foreach my $photo_detail (@{ $photo_details{$name} }) { 
     my $size  = $photo_detail->{'size'}; 
     my $position = $photo_detail->{'position'}; 

     print Dumper($photo_details{$photo}); 

     print ("size = $size, position = $position\n"); 
    } 
} 

J'ai remplacé certaines de vos parenthèses carrées et accolades. En Perl, les crochets vous donnent une référence à un tableau anonyme, et les accolades indiquent une référence à un hachage anonyme. Ils sont appelés anonymes car il n'existe pas de nom de variable explicite pour le tableau ou le hachage anonyme. Comme les structures de données Perl vous obligent à stocker une référence à un hachage plutôt que le hachage réel, vous en avez besoin pour construire les références. Vous pouvez le faire en deux étapes comme ceci:

my @array = (1, 2, 3); 
my $array_ref = \@array; 
my %hash = ('one' => 1, 'two' => 2, 'three' => 3); 
my $hash_ref = \%hash_ref; 

Pour obtenir des données sur array_ref $ et hash_ref $, vous devez l'opérateur ->:

print $array_ref->[0], "\n"; 
print $hash_ref->{one}, "\n"; 

Vous n'avez pas besoin des citations à l'intérieur de {} en référençant une clé de hachage, bien que certaines personnes considèrent les guillemets sur une clé de hachage comme une bonne pratique.

J'ai ajouté un exemple d'itération sur l'ensemble de la structure de données à titre d'exemple plutôt que de simplement regarder une référence.Voici la première ligne:

foreach my $name (keys %photo_details) { 

La méthode keys retourne toutes les clés dans un hachage, de sorte que vous pouvez les obtenir dans l'ordre. Les itère prochaine ligne sur tous les photo_detail hashrefs en% photo_details:

foreach my $photo_detail (@{ $photo_details{$photo} }) { 

Les @{ $photo_details{$photo} } les références d'la référence $photo_details{$photo} dans un tableau, que vous pouvez parcourir avec foreach.

La dernière chose que j'ai ajouté est un appel à Data::Dumper, un module très utile distribué avec Perl qui imprime des structures de données pour vous. Ceci est très pratique lors de la construction de structures de données comme celle-ci, tout comme son cousin proche Data::Dumper::Simple. Ce module n'est malheureusement pas distribué avec Perl, mais je préfère sa sortie car elle inclut des noms de variables.

Pour plus d'informations sur la création de structures de données complexes à l'aide de références, consultez perlreftut.

+0

Vous ne voulez pas dire '$ photo_details {$ name}'? – nodmonkey

+0

Oui, merci d'avoir attrapé ça. C'est réparé maintenant. –

+0

'my $ hash_ref = \% hash_ref;' - cela devrait être '\ hash'' – Richlv

14

Tout d'abord, commencez toujours chaque script ou module avec:

use strict; 
use warnings; 

Vous obtiendrez plus de messages d'avertissement et plus tôt, ce qui aide grandement le débogage.

Je ne peux pas dupliquer votre erreur: lorsque je mets ce code dans un fichier et l'exécute sans indicateurs supplémentaires, j'obtiens: size = , position =. Il n'y a pas de variable $size dans le code que vous avez imprimé, donc le message d'erreur ne correspond pas.

Néanmoins, vous déclarez vos structures de données incorrectes. Les hachages et les tableaux ne peuvent contenir que des valeurs scalaires, pas des listes: si vous voulez imbriquer un tableau ou un hachage, vous devez en faire une référence. Voir perldoc perldata, perldoc perldsc et perldoc perlreftut pour plus d'informations sur les structures de données et les références.

my %photo_details = (
    black_cat => [ 
     { size => '1600x1200', position => -25 }, 
     { size => '1280x1024', position => 25 }, 
     { size => '800x600', position => 0 }, 
    ], 
    race_car => [ 
     { size => '1600x1200', position => 10 }, 
     { size => '800x600', position => 5 }, 
    ], 
); 

foreach my $photo_detail (@{$photo_details{black_cat}}) 
{ 
    my $size  = $photo_detail->{size}; 
    my $position = $photo_detail->{position}; 

    print ("size = $size, position = $position\n"); 
} 
+3

Bon conseil et explication. Tout ce que j'ajouterais est que ce qui suit est utile dans le débogage des problèmes de structure de données Perl: use Data :: Dumper; imprimer Dumper (\% photo_details); – toolic

+0

Je suis confus, $ taille ** est ** dans l'extrait qu'il a posté, vous l'avez même porté sur votre code. Que voulais-tu dire? – lexu

+0

@lexu: oui, vous avez raison; Je pensais que l'erreur pouvait provenir de '$ photo_detail -> {$ size}' vs '$ photo_detail -> {size}'. J'ai totalement oublié la déclaration 'my $ size = ...'. Néanmoins, je ne peux pas reproduire l'erreur de l'OP. Lorsque les restrictions sont activées, le code barre plus tôt, '% photo_detail' n'étant pas déclaré (en raison de la boucle for ne déréférencant pas le tableau). – Ether

2

Il n'y a vraiment qu'une seule chose dont vous avez à vous soucier, et c'est le plus haut niveau de la structure de données. Après cela, il suffit d'utiliser la syntaxe d'indexation adaptée à chaque niveau:

Si vous avez un hachage régulier, vous accédez à la clé que vous souhaitez ensuite aligner les indices supplémentaires pour chaque niveau après:

%regular_hash = ...; 
$regular_hash{$key}[$index]{$key2}; 

Si vous avez une référence, vous faites presque la même chose, mais vous devez commencer par le déréférencement initial avec une flèche, ->, après la référence de niveau supérieur. Après cela, il est la même séquence d'indexation:

$hash_ref = ...; 
$hash_ref->{$key}[$index]{$key2}; 

Pour tous les détails, voir Intermediate Perl où nous expliquons la syntaxe de référence.

Questions connexes