如何在哈希中引用数组中的Perl哈希?

时间:2010-01-03 02:57:38

标签: arrays perl hash reference perl-data-structures

这是我正在处理的代码段:

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,po​​sition = -25

     

size = 1280x1024,position = 25

     

尺寸= 800x600,位置= 0

我得到的是:

  

在连接(。)中使用未初始化的值$ size或在C:\ Test.pl第23行使用字符串。

     

在串联(。)中使用未初始化的值$ position或在C:\ Test.pl第23行使用字符串。

     

size =,position =

foreach声明显然是错误的,因为不仅没有$ size和$ position的值,它只经历了一次而不是三次。我已经尝试了各种变量前缀的变种,但没有找到它们。

我做错了什么?

3 个答案:

答案 0 :(得分:14)

首先,始终使用以下命令启动每个脚本或模块:

use strict;
use warnings;

您将收到更多警告信息,这将大大有助于调试。

我无法复制您的错误:当我将该代码放入文件并在没有其他标志的情况下运行时,我得到:size = , position =您打印的代码中没有$size变量,因此错误消息不匹配。

然而,您正在声明您的数据结构不正确。哈希和数组可以 只包含标量值,而不是列表:所以如果你想嵌套一个数组或 哈希,你需要使它成为一个参考。见perldoc perldataperldoc perldscperldoc 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