这是我正在处理的代码段:
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");
}
我期待得到的是:
size = 1600x1200,position = -25
size = 1280x1024,position = 25
尺寸= 800x600,位置= 0
我得到的是:
在连接(。)中使用未初始化的值$ size或在C:\ Test.pl第23行使用字符串。
在串联(。)中使用未初始化的值$ position或在C:\ Test.pl第23行使用字符串。
size =,position =
foreach声明显然是错误的,因为不仅没有$ size和$ position的值,它只经历了一次而不是三次。我已经尝试了各种变量前缀的变种,但没有找到它们。
我做错了什么?
答案 0 :(得分:14)
首先,始终使用以下命令启动每个脚本或模块:
use strict;
use warnings;
您将收到更多警告信息,这将大大有助于调试。
我无法复制您的错误:当我将该代码放入文件并在没有其他标志的情况下运行时,我得到:size = , position =
。 您打印的代码中没有错误消息不匹配。$size
变量,因此
然而,您正在声明您的数据结构不正确。哈希和数组可以 只包含标量值,而不是列表:所以如果你想嵌套一个数组或 哈希,你需要使它成为一个参考。见perldoc perldata,perldoc perldsc 和perldoc perlreftut了解有关数据结构和参考的更多信息。
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");
}
答案 1 :(得分:14)
以下是一些更新的代码,解释如下:
#!/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");
}
}
我用方括号和大括号替换了一些括号。在Perl中,方括号为您提供对匿名数组的引用,而花括号表示对匿名哈希的引用。这些被称为匿名,因为匿名数组或散列没有明确的变量名称。
由于Perl数据结构使您存储对哈希的引用而不是实际哈希,因此您需要使用这些引用来构造引用。您可以通过以下两个步骤执行此操作:
my @array = ( 1, 2, 3 );
my $array_ref = \@array;
my %hash = ( 'one' => 1, 'two' => 2, 'three' => 3 );
my $hash_ref = \%hash_ref;
要从$ array_ref和$ hash_ref中获取数据,您需要 - >操作者:
print $array_ref->[0], "\n";
print $hash_ref->{one}, "\n";
在引用散列键时,您不需要{}内的引号,尽管有些人认为散列键上的引号是很好的做法。
我在整个数据结构上添加了一个迭代示例作为示例,而不仅仅是查看一个引用。这是第一行:
foreach my $name ( keys %photo_details ) {
keys方法返回哈希中的所有键,以便您可以按顺序获取它们。下一行迭代%photo_details中的所有photo_detail hashref:
foreach my $photo_detail ( @{ $photo_details{$photo} } ) {
@{ $photo_details{$photo} }
将引用$photo_details{$photo}
取消引用到数组中,您可以使用foreach迭代它。
我添加的最后一件事是调用Data::Dumper,这是一个与Perl一起分发的非常有用的模块,可以为您打印出数据结构。在构建像这样的数据结构时,这非常方便,与其密切相关的表兄Data::Dumper::Simple也是如此。遗憾的是,这个模块没有与Perl一起发布,但我更喜欢它的输出,因为它包含变量名。
有关如何使用引用构建复杂数据结构的进一步阅读,请查看perlreftut。
答案 2 :(得分:2)
实际上只有一件事你需要担心,这是数据结构的最高层。之后,您只需为每个级别使用正确的索引语法:
如果您有常规哈希,则可以访问所需的密钥,然后为其后的每个级别排列其他索引:
%regular_hash = ...;
$regular_hash{$key}[$index]{$key2};
如果你有一个参考,你几乎做同样的事情,但你必须在顶级参考之后用箭头->
开始初始取消引用。之后它是相同的索引序列:
$hash_ref = ...;
$hash_ref->{$key}[$index]{$key2};
有关所有细节,请参阅我们解释参考语法的Intermediate Perl。