2011-12-27 82 views
2

我在访问数据时遇到问题,在问题的标题中进行了描述。
数据的结构如下:阵列引用数组散列数组

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)数组的元素@ TEST3

好吧,在你的结构,这将会是:

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}是对@structure阵列中第一项中散列元素Data2的引用。这是对数组的引用。
  • $structure[0]->{Data2}->[0]是对@structure数组的第一个元素(0)中的Data2散列元素中第一个数组引用的引用。这是你的@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,并通过面向对象编程。

+0

非常感谢您的时间和建议!使用这样复杂的结构对我来说是个例外,我觉得OOP还为时过早。但我一定会在将来研究它。 – evgeny9 2011-12-29 16:58:23

4

print $structure[0]{'Data2'}[0][0];将工作!

你只是忘记了最后一关!

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

@{$_->{'Data2'}}[0]为您提供了匿名数组的第一个元素,即对另一个数组的引用!如果你有"Data2" => \@test3,而不是"Data2" => [\@test3],

+0

感谢您的简短实际答案 - 它的工作。 – evgeny9 2011-12-29 17:00:09

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

您的代码会工作。

+0

谢谢 - 您的工作示例确实帮助我消除了错误(最初,结构太复杂)。 – evgeny9 2011-12-29 17:02:12