Perl,(更容易)访问哈希变量

Chr*_*s R 1 perl

我创建了一个子函数,它返回对包含7-8个变量的属性哈希的引用.每当我想访问一个元素时,我要么重新定义它,my $n_players = $ref_attr->{'n_players'}要么直接调用它$ref_attr->{'n_players'}.我宁愿使用所有重新定义的变量(第一种情况)但是这需要7-8行初始化并使我的代码混乱.

是否有一个模块(我似乎无法找到)或导出散列键用作变量的好方法?

cjm*_*cjm 8

您可以使用散列片来减少从散列中获取多个条目所涉及的重复.例如,您可以在初始化副本时使用此功能(假设您还有一个n_teams条目):

my ($n_players, $n_teams) = @$ref_attr{qw( n_players n_teams )};
Run Code Online (Sandbox Code Playgroud)

正如Eric Strom建议的那样,您还可以使用缩进来确保按正确的顺序获得密钥:

my ($n_players, $n_teams) = @$ref_attr{
 qw( n_players   n_teams)
};
Run Code Online (Sandbox Code Playgroud)

正如其他人所说,可以操纵符号表来创建与每个键对应的变量,但这不是一个好主意.


Eri*_*rom 5

您可以使用引用和哈希切片轻松完成此操作:

sub takes_hashref {
    my $hashref = shift;

    my ($one, $two, $three, $four, $five) = \@$hashref{
      qw(one   two   three   four   five)
    };

    print "one: $$one, two: $$two, three: $$three, ",
          "four: $$four, five: $$five\n";

    $_++ for $$one, $$three, $$five;
}

my %hash = qw(one 1 two 2 three 3 four 4 five 5);

takes_hashref \%hash; # one: 1, two: 2, three: 3, four: 4, five: 5
takes_hashref \%hash; # one: 2, two: 2, three: 4, four: 4, five: 6
takes_hashref \%hash; # one: 3, two: 2, three: 5, four: 4, five: 7
Run Code Online (Sandbox Code Playgroud)

@$hashref{qw(x y z)}是一个哈希切片,它返回值列表.Prepending \接受每个值的引用并返回引用列表.然后将其分配给词法变量.当你使用每个变量时,将sigil加倍以取消引用它:$$var.由于这些变量包含对哈希字段的引用,因此您可以为它们分配:$$var = 'new val',并且赋值将更改原始哈希.如果您不关心传播回散列的变量的更改,则可以省略\散列切片上的变量,以及所有变量上的双重签名.

如果您只想创建一个较短的别名来使用,可以%_在sub中进行本地化:

sub takes_hashref2 {
    my $hashref = shift;

    local *_ = \%$hashref;

    print "one: $_{one}, two: $_{two}, three: $_{three}, ",
          "four: $_{four}, five: $_{five}\n";

    $_++ for @_{qw(one three five)};
}

my %hash = qw(one 1 two 2 three 3 four 4 five 5);

takes_hashref2 \%hash; # one: 1, two: 2, three: 3, four: 4, five: 5
takes_hashref2 \%hash; # one: 2, two: 2, three: 4, four: 4, five: 6
takes_hashref2 \%hash; # one: 3, two: 2, three: 5, four: 4, five: 7
Run Code Online (Sandbox Code Playgroud)

该行的local *_ = \%$hashref别名%_为哈希$hashref.该\%部分不是必需的,但如果值$hashref不是哈希值,则会抛出错误.它只是一种较短的写作方式:

die 'not a hash' unless ref $hashref eq 'HASH';
local *_ = $hashref;
Run Code Online (Sandbox Code Playgroud)

你可以把它写成一行:

local *_ = \%{shift @_};
Run Code Online (Sandbox Code Playgroud)