Perl数组引用包含哈希中的键数,而不是实际的键

时间:2014-06-07 12:08:23

标签: 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将包含哈希的键。 问题是区别在哪里?

2 个答案:

答案 0 :(得分:3)

use strict;use warnings;一样有用,请尝试

@$arr_ref = keys($hash);

因为$arr_ref = keys($hash);$arr_ref = scalar keys($hash);的隐式版本,并且在两种情况下都会确保标量为context

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

答案 1 :(得分:3)

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

以下列出了您需要记住的事项:

  • $hash$arr_ref都是引用,因此变量名称有$,因为它们只存储实际哈希/数组所在的内存地址引用。
  • 一个数组有一个@ sigil,一个哈希有一个% sigil。因此@array%hash都是引用。
  • 如果要将数据结构放入Perl中的另一个数据结构中,则需要引用它。这是通过将\放在变量名称前面来完成的,例如$ref = \@array
  • 数组获得分配的列表:my @colors = ( 'red', 'green' );
  • 哈希获得分配的列表(带括号):%count = ( 'red' => 5, 'green' => 2 );
  • 要访问哈希值,请使用$count{'red'}。 sigil更改为$,因为整个标识符count{'red'}后面的值现在是标量值。
  • 要访问数组值,请使用$colors[0](将提供'red'
  • keys函数返回一个列表。
  • 将列表或数组强制转换为标量上下文将给出其元素数。

现在掌握了所有这些知识,您将看到当您将keys($hash)分配给$arr_ref时,您正在强制使用标量上下文,从而获得计数。

  • 如果您想要一组密钥,请使用my @array = keys($hash)
  • 如果您需要数组引用,请使用my $arr_ref = \keys($hash)或将keys返回的列表放入类似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