Perl:数组和哈希

时间:2016-10-14 18:29:25

标签: arrays perl

为了找到我之前的问题Perl: slicing an array of hashes的答案,我再次陷入困境,无法看到我做错了什么。

我拥有的是

数组(Array0(Hash0,Hash1),Array1(Hash0,Hash1),Array2(Hash0,Hash1)......)

use strict;
use warnings;

my @DDs = ();
my @Ds  = ();
my %hsh = ();

my %dot1 = ( 'x' => 1,   'y' => 2,   'r' => 3 );
my %dot2 = ( 'x' => 4,   'y' => 5,   'r' => 6 );
my %dot3 = ( 'x' => 7,   'y' => 8,   'r' => 9 );
my %dot4 = ( 'x' => 1.1, 'y' => 1.2, 'r' => 1.3 );
my %dot5 = ( 'x' => 2.1, 'y' => 2.2, 'r' => 2.3 );
my %dot6 = ( 'x' => 3.1, 'y' => 3.2, 'r' => 3.3 );
my %dot7 = ( 'x' => 4.1, 'y' => 4.2, 'r' => 4.3 );
my %dot8 = ( 'x' => 5.1, 'y' => 5.2, 'r' => 5.3 );

my @dotsA = ( \%dot1, \%dot2 );
my @dotsB = ( \%dot3, \%dot4 );
my @dotsC = ( \%dot5, \%dot6 );
my @dotsD = ( \%dot7, \%dot8 );

my %Ds = ( \@dotsA, \@dotsB, \@dotsC, \@dotsD );

@DDs = $Ds[1];    #expect @dotsB with scalar of 2

###"Can't use an undefined value as HASH reference" error here
%hsh = %{ $DDs[0] };    #expect %dot3

print scalar @DDs, "\n";    #expect 2 but has value of 1
print $hsh{'x'}, "\n";

1 个答案:

答案 0 :(得分:6)

  

参考文献找到了/Users/schwern/tmp/test.plx第10行的预期大小列表。

第10行是这样的:

my %dot1 = {'x'=>1,'y'=>2,'r'=>3};

这是Perl的一种神秘的方式,说你给哈希提供了一个哈希引用。不幸的是,Perl在事物和对事物的引用之间存在很大差异。

%dot1是一个哈希值。它需要一个列表并将其转换为哈希值。像( x => 1, y => 2, r => 3)这样的列表。 { x => 1, y => 2, r => 3 }创建哈希引用。这是一个单一的东西,一个标量。这就像说my %dot1 = (42)。这没有任何意义。

  • %dot1是一个哈希,它需要一个像(x => 1, y => 2)
  • 这样的列表
  • $ dot1是一个标量,它可以存储像{ x => 1, y => 2 }这样的哈希引用。
my %Ds = (\@dotsA,\@dotsB,\@dotsC,\@dotsD);

散列需要键和值,对。 last_name => "Schwern"。当你给它一堆像这样的数组引用时,它会将它们读作key1,value1,key2,value2 ......但是它用作键是什么?它正在使用该引用的字符串化,例如ARRAY(0x7fb721800468)

如果您要求$D{\@dotsA},您将获得对@dotsB的引用。您将无法返回@dotsA,Perl哈希键只是一个字符串,而不是引用。

这不是一个在哈希中存储数组的好方法。我不确定你要完成什么,但你可能想要通过名字来引用它们。

# A hash of lists.
my %Ds = ( A => \@dotsA, B => \@dotsB, C => \@dotsC, D => \@dotsD );

# Get back a reference to @dotsA.
my $dotsA = $Ds{A};

但是查看以下代码@DDs = $Ds[1];,我认为您打算初始化@Ds而不是%Ds

@Ds = (\@dotsA,\@dotsB,\@dotsC,\@dotsD);

现在以下作品......有点儿。更晚些时候。

@DDs = $Ds[1]; #expect @dotsB with scalar of 2

与PHP不同,哈希和数组是完全不同的东西。 my @Dsmy %Ds声明了完全不同的变量。使用$Ds访问它们无关紧要。在Perl5中,sigil表示将返回什么。 $Ds[1]$Ds{foo}都使用$Ds因为它们返回标量。 @Ds[1,2]@Ds{(foo, bar)}使用@Ds因为他们返回了一个列表(称为切片)。令人困惑,但这就是它的工作原理。

@DDs = $Ds[1]; #expect @dotsB with scalar of 2

您未获得@dotsB,而是获得对@dotsB的引用。 Perl中的所有复杂数据结构都存储引用,而不是实际值。这就像$DDs[0] = \@dotsB。如果你想获得实际值,你必须取消引用它。

@DDs = @{$Ds[1]};  # Now @DDs has a copy of @dotsB

最后它有效。

#!/usr/bin/perl
use strict;
use warnings;
use v5.10;    # for say()

my %dot1 = ('x'=>1,'y'=>2,'r'=>3);
my %dot2 = ('x'=>4,'y'=>5,'r'=>6);
my %dot3 = ('x'=>7,'y'=>8,'r'=>9);
my %dot4 = ('x'=>1.1,'y'=>1.2,'r'=>1.3);
my %dot5 = ('x'=>2.1,'y'=>2.2,'r'=>2.3);
my %dot6 = ('x'=>3.1,'y'=>3.2,'r'=>3.3);
my %dot7 = ('x'=>4.1,'y'=>4.2,'r'=>4.3);
my %dot8 = ('x'=>5.1,'y'=>5.2,'r'=>5.3);

my @dotsA = (\%dot1,\%dot2);
my @dotsB = (\%dot3,\%dot4);
my @dotsC = (\%dot5,\%dot6);
my @dotsD = (\%dot7,\%dot8);

my @Ds = (\@dotsA,\@dotsB,\@dotsC,\@dotsD);
my @DDs = @{$Ds[1]}; #expect @dotsB

my %hsh = %{$DDs[0]}; #expect %dot3

say scalar @DDs; #expect 2
say $hsh{'x'};

我还建议您直接使用引用,因为这就是复杂的数据结构:引用。从引用到值的来回转换是令人困惑的。使用引用只需要在代码中转换,在头脑中转换,并减少在程序中完成的复制。

#!/usr/bin/perl
use strict;
use warnings;
use v5.10;    # for say()

my $dot1 = {'x'=>1,'y'=>2,'r'=>3};
my $dot2 = {'x'=>4,'y'=>5,'r'=>6};
my $dot3 = {'x'=>7,'y'=>8,'r'=>9};
my $dot4 = {'x'=>1.1,'y'=>1.2,'r'=>1.3};
my $dot5 = {'x'=>2.1,'y'=>2.2,'r'=>2.3};
my $dot6 = {'x'=>3.1,'y'=>3.2,'r'=>3.3};
my $dot7 = {'x'=>4.1,'y'=>4.2,'r'=>4.3};
my $dot8 = {'x'=>5.1,'y'=>5.2,'r'=>5.3};

my $dotsA = [$dot1,$dot2];
my $dotsB = [$dot3,$dot4];
my $dotsC = [$dot5,$dot6];
my $dotsD = [$dot7,$dot8];

my $Ds = [$dotsA,$dotsB,$dotsC,$dotsD];
my $DDs = $Ds->[1]; #expect $dotsB

my $hsh = $DDs->[0]; #expect $dot3

say scalar @$DDs; #expect 2
say $hsh->{'x'};

您应该查看perlreftutNested Data Structures chapter of Modern Perl