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

时间:2011-01-29 22:52:57

标签: perl

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

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

5 个答案:

答案 0 :(得分:8)

您可以使用hash slices来减少从哈希中获取多个条目所涉及的重复次数。例如,您可以在初始化副本时使用此功能(假设您还有n_teams条目):

my ($n_players, $n_teams) = @$ref_attr{qw( n_players n_teams )};

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

my ($n_players, $n_teams) = @$ref_attr{
 qw( n_players   n_teams)
};

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

答案 1 :(得分: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

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

如果您只想创建一个较短的别名,可以在子资源中本地化%_

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

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

die 'not a hash' unless ref $hashref eq 'HASH';
local *_ = $hashref;

你可以把它写成一行:

local *_ = \%{shift @_};

答案 2 :(得分:3)

别。要么明确地复制它们(你的第一个选项),要么只使用哈希(你的第二个选项)。从长远来看,这是非常清楚的。

...

但是如果你真的想,那么哈希%::是你当前的包变量hash(是的,perl internals)。你可以玩它。

perl -e'print %::';

答案 3 :(得分:3)

我是哈曼的第二个建议(不要),但如果你想要它的话:

my %vars = ( a => 1, b => 2 );

while (my ($k,$v) = each %vars) {
    $::{$k} = \$v;
}

print "a=$a, b=$b\n";

答案 4 :(得分:0)

另一种选择是为您的数据集合创建一个类,并让子函数返回该类的实例(对象)而不是普通的hashref。然后,您将访问值$returned_object->n_players。在这种特殊情况下,它在保存的打字方面或者与$ref_attr->{n_players}相比没有真正为你带来太多的购买,但是去OOP开辟了很多可能性(例如,只读或计算属性)随着您的计划不断发展,或者未来证明有用。