2014-06-07 25 views
0

明显存在扭曲。当我这样做,它的作品,并包含所有的按键:Perl数组引用包含散列中的密钥数量,而不是实际的密钥

my $hash = {}; 
$$hash{1} = "asd"; 
$$hash{21} = "fafafa"; 

for my $key (keys($hash)) 
{ 
    push($arr_ref, $key); 
} 

print Dumper($arr_ref); 

然而,当我尝试做以下方式我只拿到钥匙的数量:

my $hash = {}; 
    $$hash{1} = "asd"; 
    $$hash{21} = "fafafa"; 
    my $arr_ref = []; 
    $arr_ref = keys($hash); 

在我头上这两件事应该是相同的,所有,如果我那样做之后:

my @arr = keys($hash); 

@arr将包含哈希键。 问题是区别在哪里?

+0

您对Perl的变量类型的性质感到困惑。例如,'my $ hash = {};'这两行在你的例子中都没有任何用处。删除该行,它将没有区别。 Perl变量是最后分配给它的类型。因此,虽然'my $ arr_ref = [];'这一行使'$ arr_ref'成为此时数组的引用,'$ arr_ref = keys($ hash)'行为'keys()'提供了一个标量上下文,导致返回数组的长度。它需要是'@ $ arr_ref = keys($ hash)'来提供一个数组上下文。 – ooga

回答

3

你在这里有一些困惑。如果sigil(var名称前面的符号)是$,则表示有标量值。

以下是你需要记住的事情的清单:

  • 两个$hash$arr_ref是引用,所以变量名有$,因为他们只存储一个存储器地址引用到实际的散列/阵列是。
  • 一个数组有一个@印记,并且一个散列有一个%印记。所以@array%hash都是而不是的引用。
  • 如果你想在Perl中把数据结构放到另一个数据结构中,你需要引用它。这是通过将\放在变量名称前面来完成的,如$ref = \@array
  • 数组获取分配列表:分配my @colors = ('red', 'green');
  • 散列得到的列表(括号用):%count = ('red' => 5, 'green' => 2);
  • 要访问的散列值,使用$count{'red'}。由于整个标识符count{'red'}后面的值现在是标量值,因此sigil更改为$
  • 要访问的数组值,则使用$colors[0](这将给'red'
  • keys函数返回的列表。
  • 强制列表或数组成标量环境会给其元素的个数。

现在有了这些知识,你会看到,当你分配给keys($hash)$arr_ref,您强制标量上下文,因此你得到的计数。

  • 如果您想要一个密钥数组,请使用my @array = keys($hash)
  • 如果你想要一个数组参考,使用my $arr_ref = \keys($hash)或将keys返回的列表放入数组ref,如my $arr_ref = [ keys($hash) ]

另请注意,Perl的keys built-in最近才学会处理引用。你应该给它一个哈希值,或像keys(%{ $hash_ref })一样取消引用你的哈希引用。这可以缩短为keys %$hash_ref

此外,总是use strictuse warnings,因为这两者都会告诉你你做错了什么或者你可能会感到困惑的事情。


为了说明更多,我已将您的第一段代码重写为三种不同的形式。

没有引用:

use strict; 
use warnings; 
use Data::Dumper; 

my %hash = (
    1 => "asd", 
    21 => "fafafa" 
); 

my @array_of_keys =(); 
for my $key (keys %hash) 
{ 
    push @array_of_keys, $key; 
} 

print Dumper(\@array_of_keys); # reference the array because it looks nicer in Dumper 

参考的数组:

use strict; 
use warnings; 
use Data::Dumper; 

my %hash = (
    1 => "asd", 
    21 => "fafafa" 
); 

my $arrayref_of_keys = []; 
for my $key (keys %hash) 
{ 
    push @$arrayref_of_keys, $key; # or @{ $foo } 
} 

print Dumper($arrayref_of_keys); # it's already a ref, so no need for \ 

的所有引用:

use strict; 
use warnings; 
use Data::Dumper; 

my %hashref = { # notice the curly braces instead of round parens 
    1 => "asd", 
    21 => "fafafa" 
}; 

my $arrayref_of_keys = []; 
for my $key (keys %$hashref) # or %{ $foo } 
{ 
    push @$arrayref_of_keys, $key; # or @{ $foo } 
} 

print Dumper($arrayref_of_keys); 

我建议你阅读perlrefperlreftut

+0

+1了解非常详细的答案。 – Bloodcount

+0

它只是得到更详细的;) – simbabque

+0

作为一个侧面说明,想想什么时候你想使用引用,当你不需要。 – simbabque

3

use strict;将与use warnings;一起帮助,尝试

@$arr_ref = keys($hash); 

$arr_ref = keys($hash);$arr_ref = scalar keys($hash);隐含的版本,并确保标context在这两种情况下。

另请注意,keys $scalarexperimental,建议使用keys %$scalar