Arrays 如何在散列中的数组中引用Perl散列?

Arrays 如何在散列中的数组中引用Perl散列?,arrays,perl,hash,reference,perl-data-structures,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' =&g

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

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");
}
我期望得到的是:

尺寸=1600x1200,位置=-25

大小=1280x1024,位置=25

尺寸=800x600,位置=0

我得到的是:

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

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

大小=,位置=

foreach语句显然是错误的,因为它不仅没有$size和$position的值,而且只循环了一次而不是三次。我尝试了各种各样的变量前缀,但没有发现一种是有效的


我做错了什么?

首先,始终以以下内容开始每个脚本或模块:

use strict;
use warnings;
您将得到更多的警告消息,并且更快,这将大大有助于调试

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

但是,您的数据结构声明不正确。散列和数组可以 只包含标量值,而不包含列表:因此如果要嵌套数组或 一个散列,你需要把它作为参考。看见 以及有关数据结构和引用的更多信息

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");
}

以下是一些更新的代码,解释如下:

#!/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\u ref和$hash\u ref中获取数据,需要->运算符:

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

当引用哈希键时,您不需要{}内的引号,尽管有些人认为散列键上的引号是很好的做法。p> 我添加了一个对整个数据结构进行迭代的示例作为示例,而不仅仅是查看一个引用。这是第一行:

foreach my $name ( keys %photo_details ) {
keys方法返回散列中的所有键,以便按顺序获取它们。下一行迭代%photo\u details中的所有photo\u details hashref:

    foreach my $photo_detail ( @{ $photo_details{$photo} } ) {
@{$photo\u details{$photo}
将引用
$photo\u details{$photo}
反引用到一个数组中,您可以使用foreach对其进行迭代

我添加的最后一件事是调用,这是一个非常有用的模块,由Perl分发,可以为您打印数据结构。当构建这样的数据结构时,这是非常方便的,它的近亲也是如此。不幸的是,这个模块没有用Perl分发,但我更喜欢它的输出,因为它包含变量名


有关如何使用引用构建复杂数据结构的进一步阅读,请参阅

实际上只有一件事需要担心,那就是数据结构的顶层。之后,您只需为每个级别使用正确的索引语法:

如果您有一个常规散列,那么您可以访问所需的密钥,然后在该密钥之后为每个级别排列附加索引:

 %regular_hash = ...;
 $regular_hash{$key}[$index]{$key2};
如果您有一个引用,您可以做几乎相同的事情,但是您必须在顶级引用之后用箭头开始初始取消引用,
->
。之后是相同的索引顺序:

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

有关所有详细信息,请参见我们在何处解释引用语法。

我很困惑,$size肯定在他发布的代码片段中,您甚至将其带到了代码中。你什么意思?@雷克萨斯:是的,你说得对;我想这个错误可能是因为使用了
$photo\u detail->{$size}
vs
$photo\u detail->{size}
。我完全忽略了
my$size=…
声明。然而,我不能复制OP的错误。启用strictures后,代码会在前面的
%photo\u detail
处出现条带(由于for循环未取消对数组的引用)。感谢您的解释。数据结构现在看起来确实不错。但是,如果我尝试上面的代码,我会在第20行和第21行得到“全局符号“%photo\u detail”需要显式的包名”。我阅读了文档(谢谢),将foreach语句更改为
[foreach my$photo_detail(@{%photo_details->{black_cat}]),将
[$photo_detail{size}]更改为
[$photo_detail->{size}],并将
[$photo_details{position position position}]更改为`[$photo_details->{positionforeach行上的“使用散列作为参考是不推荐的”。有什么想法吗?@我没有对你的逻辑提出错误,只有$size的语句让我感到困惑!OP似乎在学习符号和范围的使用。两者一开始都令人困惑。(+1,我给你一个好建议)@TallGuy:在“perldoc perlwarn”中查找警告消息是一种信息:您的foreach行有标点错误。您的意思是
$photo\u details{$name}
我的$hash\u ref=\%hash\u ref;
-那应该是
\%hash
我这里只有一个问题:为了便于描述,我们可以将这个数据结构称为
哈希数组的哈希吗?