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

发布于 2024-08-16 06:23:59 字数 1029 浏览 10 评论 0原文

这是我正在使用的代码片段:

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 没有值,而且它只循环了一次而不是三次。我尝试了各种变量前缀的变体,但发现没有一个有效。

我做错了什么?

This is the code snippet I am working with:

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

What I am expecting to get is:

size = 1600x1200, position = -25

size = 1280x1024, position = 25

size = 800x600, position = 0

What I do get is:

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 =

The foreach statement is clearly wrong as not only are there no values for $size and $position, it has only gone through the loop once instead of three times. I have tried all sorts of variants of variable prefixes and found none that work.

What am I doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

雪若未夕 2024-08-23 06:23:59

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

#!/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 哈希引用:

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

@{ $photo_details{$photo} } 将引用 $photo_details{$photo} 取消引用为一个数组,您可以使用 foreach 对其进行迭代。

我添加的最后一件事是对 Data::Dumper 的调用,这是一个非常有用的与 Perl 一起分发的模块,可以为您打印出数据结构。在构建这样的数据结构时,这非常方便,与其密切相关的表兄弟数据也是如此: :转储器::简单。不幸的是,这个模块没有随 Perl 一起分发,但我更喜欢它的输出,因为它包含变量名称。

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

Here is some updated code, with an explanation below:

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

I've replaced some of your parentheses with square and curly brackets. In Perl, square brackets give you a reference to an anonymous array, and curly brackets denote a reference to an anonymous hash. These are called anonymous because there's no explicit variable name for the anonymous array or hash.

As Perl data structures make you store a reference to a hash rather than the actual hash, you need these to construct the references. You can do this in two steps like this:

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

To get data out of $array_ref and $hash_ref, you need the -> operator:

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

You don't need the quotes inside of the {} when referencing a hash key, although some people consider quotes on a hash key to be good practice.

I added an example of iteration over the entire data structure as an example rather than just looking at one reference. Here's the first line:

foreach my $name ( keys %photo_details ) {

The keys method returns all of the keys in a hash, so that you can get them in order. The next line iterates over all of the photo_detail hashrefs in %photo_details:

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

The @{ $photo_details{$photo} } de-references the reference $photo_details{$photo} into an array, which you can iterate over it with foreach.

The last thing that I added is a call to Data::Dumper, a very useful module distributed with Perl that prints out data structures for you. This is very handy when building up data structures like this, as is its closely related cousin Data::Dumper::Simple. This module is unfortunately not distributed with Perl, but I prefer its output as it includes variable names.

For some further reading about how to build up complex data structures using references, check out perlreftut.

墟烟 2024-08-23 06:23:59

首先,始终以以下方式启动每个脚本或模块:

use strict;
use warnings;

您将更快地收到更多警告消息,这极大地有助于调试。

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

尽管如此,您声明的数据结构不正确。哈希和数组可以
仅包含标量值,而不包含列表:因此如果您想嵌套数组或
哈希值,您需要将其作为引用。请参阅 perldoc perldataperldoc 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");
}

First of all, always start every script or module with:

use strict;
use warnings;

You will get more warning messages and sooner, which greatly helps debugging.

I cannot duplicate your error: when I put that code into a file and run it with no additional flags, I get: size = , position =. There is no $size variable in the code you printed, so the error message does not match.

Nevertheless, you are declaring your data structures incorrectly. Hashes and arrays can
only contain scalar values, not lists: so if you want to nest an array or
a hash, you need to make it a reference. See perldoc perldata, perldoc perldsc
and perldoc perlreftut for more about data structures and references.

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");
}
你列表最软的妹 2024-08-23 06:23:59

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

如果您有一个常规哈希,您可以访问所需的键,然后在其后为每个级别排列附加索引:

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

如果您有一个引用,您几乎可以执行以下操作:同样的事情,但是您必须在顶级引用之后使用箭头 -> 开始初始取消引用。之后是相同的索引序列:

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

有关所有详细信息,请参阅 Intermediate Perl,其中我们解释了引用语法。

There's really only one thing you have to worry about, and that's the top level of the data structure. After that, you just use the right indexing syntax for each level:

If you have a regular hash, you access the key that you want then line up the additional indices for each level after it:

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

If you have a reference, you do almost the same thing, but you have to start off with the initial dereference with an arrow, ->, after the top-level reference. After that it's the same indexing sequence:

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

For all of the details, see Intermediate Perl where we explain reference syntax.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文