我在访问数据时遇到问题,如问题标题所述 数据的结构如下:
my @structure = (
{
"Name" => "Test",
"Param1" => 1,
"Data1" => \@test1,
"Data2" => [\@test3],
"Data3" => [\@test1, \@test2],
},
...
);
我需要访问数组@test3
的第一个(#0)元素
我试过这样的事情:
my @array = @{$_->{'Data2'}}[0];
print $array[0];
但是后来我得到了对数组(ARRAY(0x239c3c)
)的引用,而不是所需的含义。我觉得这里有一些我不明白的全球性事物
难道你不能解释我应该如何以及为什么要达到所要求的含义?
非常感谢。
答案 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并查看面向对象编程的内容。