数组引用数组的哈希数组

时间:2011-12-27 17:36:39

标签: arrays perl reference hash

我在访问数据时遇到问题,如问题标题所述 数据的结构如下:

my @structure = (
  {
   "Name" => "Test",
   "Param1" => 1,
   "Data1" => \@test1,
   "Data2" => [\@test3],
   "Data3" => [\@test1, \@test2],    
  },
  ...
);

我需要访问数组@test3的第一个(#0)元素 我试过这样的事情:

my @array   = @{$_->{'Data2'}}[0];
print $array[0];

但是后来我得到了对数组(ARRAY(0x239c3c))的引用,而不是所需的含义。我觉得这里有一些我不明白的全球性事物 难道你不能解释我应该如何以及为什么要达到所要求的含义? 非常感谢。

3 个答案:

答案 0 :(得分:4)

print $structure[0]{'Data2'}[0][0];会有效!

你忘记了最后一级!

$_->{'Data2'}是对匿名数组的引用。

@{$_->{'Data2'}}[0]为您提供匿名数组的第一个元素,即对另一个数组的引用!

如果您使用"Data2" => \@test3,代替"Data2" => [\@test3],

,您的代码就可以使用

答案 1 :(得分:4)

use strict;
use warnings;

my @test1 = (1,2,3);
my @test2 = (4,5,6);
my @test3 = (7,8,9);

my @structure = (
  {
   "Name" => "Test",
   "Param1" => 1,
   "Data1" => \@test1,
   "Data2" => [\@test3],
   "Data3" => [\@test1, \@test2],
  }
);

print $structure[0] # $structure is an array, you want first element...
  ->{'Data2'}       # ...which is a hash reference, you want value for 'Data2'...
  ->[0]             # ...which is holding an array reference to (one element) array @test3...
  ->[0];            # ...which is an array reference, and you want first element

打印7

答案 2 :(得分:3)

您可以使用->的语法糖来获取所需的参考。它比使用括号要清晰得多。

  

我需要访问数组@ test3的第一个(#0)元素

好的,在你的结构中,它是:

my $element = $structure[0]->{Data2}->[0]->[0];

这是等同的,但更难阅读:

my $element = ${${${$structure[0]}{Data2}}[0]}[0];

并且,在这种特殊情况下,您可以消除语法糖->

my $element = $structure[0]{Data2}[0][0];

但是,我不知道这是否更容易阅读,并且有些情况下,默认的解析方式可能无法完全按照您的意愿执行。当我指的是数组数组时,我倾向于挤压所有内容,但就是这样:

my $element = $array[0][3];     #This is okay
my $element = $array[0]->[3];   #Same as above, but with -> syntax

否则,我将使用->的语法甜味剂。

以下是语法的解释:

  • $structure[0]是对@structure数组的第一项的引用。这包含对哈希的引用。
  • $structure[0]->{Data2}是对Data2数组中第一项中哈希元素@structure的引用。这是对数组的引用。
  • $structure[0]->{Data2}->[0]是对Data2数组的第一个元素(0)中@structure哈希元素中第一个数组引用的引用。这是您的@test3数组。
  • $structure[0]->{Data2}->[0]->[0]@test3数组的第一个元素。

我还建议您在编写代码时使用Data::Dumper模块。它可以帮助您了解您引用的结构,并帮助指出级别中的任何错误。例如:

use Data::Dumper;

print $structure[0]->{Data2}->[0] . "\n";

将向您显示这是对另一个数组层的引用。

print "$structure[0]\n";

将向您显示这是对哈希的引用,其中每个项目都包含对数组数组的引用。


无论何时使用这些高度复杂的结构,它都会因使用面向对象的Perl编码而尖叫。我不是100%肯定你正在做什么,所以我无法帮助你处理你的物体,但是高度复杂的结构往往会破坏并且几乎不可能维持。

例如,我们现在这样做:

use strict;
use warnings;

my $Foo = "bar";
print "Foo = $foo\n";

通过执行$foo代替$Foo,可以快速检测到我拼错了我的变量名称。与旧版本的Perl相比,这是一项重大改进,无法进行此类错误检查。

然而,现在看看:

use strict;
use warnings;

my %hash;
$hash{Foo} = "bar";
print "Foo = $hash{foo}\n";

我们丢失了编译错误检查。 %hash是合法变量,但$hash{Foo}已定义,而非$hash{foo}。在这种情况下,use strict对您没有任何作用。

使用面向对象的Perl返回此错误检查:

use strict;
use warnings;
use Object::Foo;

my $hash = Object::Foo->new;
$hash->Foo(bar);
print "Foo = " . $hash->foo . "\n";

糟糕!该方法应为Foo而不是foo。但是,Perl能够检测到方法foo不存在,并且会在编译时再次生成错误。

在上面的例子中,它非常简单,但你正在处理数组数组的哈希数组。每次参考访问都会将错误的可能性乘以100。而且,由于您必须在代码中反复拼写这些引用,因此错误可能位于数十个不同的位置。即使您最初可以对此进行编码,然后在代码中对整个结构进行注释,但是当您在三个月后回到此状态时,也无法保持这一点。

查看Perldoc's Tutorials并查看面向对象编程的内容。