Perl hash ref return: { 'a' =>1, % { sub() } }


{ 'a' =>1, % { sub() } }

这是否最适合将作为ref返回的散列包含到其他散列中?

%$sub()不工作。

到目前为止,我new{}生成新的散列并返回引用,可能是new优化掉了这种情况,但不确定。

我猜您有一些返回哈希引用的子例程,并且您希望将所有这些键都包含在一个更大的哈希中:

my $hash_ref = some_sub(...);
my $big_hash = { a => 1 };

有几种方法可以做到。在你的问题中,看起来你试图通过取消引用返回值来内联。这可能是合理的。环绕符号或后缀取消引用可以做到这一点:

# general circumfix (old way)
my $big_hash = { a => 1, %{ some_sub() } };
# postfix dereference (new v5.24 hotness)
my $big_hash = { a => 1, some_sub()->%* };

然而,我往往不喜欢直接这么做。通常,当默认值可能被some_sub()覆盖时,我会这样做:

my %defaults = ( ... );
my %big_hash = ( %defaults, some_sub()->%* );

但是,我通常会更进一步,将产生默认值的东西放入另一个子例程中,这样我就可以给子类一种覆盖它的方法:

sub defaults {
my %defaults = ( ... );
return %defaults;
}
my %big_hash = ( defaults()->%*, some_sub()->%* );

还有许多其他方法可以合并哈希。有"如何在Perl中组合哈希?"?关于StackOverflow,还有我如何在perlfaq4中合并两个哈希。

但是,还有一件事需要考虑。简单地将两个散列混合在一起得到一个新散列可能代价高昂。如果第一个散列非常非常大怎么办?

my %grand_hash = ( %very_big_hash, %new_hash );

人们经常这样做,并将其分配回起始散列,主要是因为它很容易键入:

my %grand_hash = ( %grand_hash, %new_hash );

您告诉Perl展开%grand_hash,将另一个列表与之组合,然后重新散列这个巨大的列表。

虽然有点笨拙,但更好的方法是添加新的键和值。

foreach my $new_key ( keys %new_hash ) {
$grand_hash{$new_key} = $new_hash{$new_key};
}

当你需要做其他事情时,这很好,比如跳过哈希中已经存在的密钥:

foreach my $new_key ( keys %new_hash ) {
next if exists $grand_hash{$new_key};
$grand_hash{$new_key} = $new_hash{$new_key};
}

或者可能添加到已经存在的值而不是替换它:

foreach my $new_key ( keys %new_hash ) {
$grand_hash{$new_key} += $new_hash{$new_key};
}

如果你只需要添加它,而不关心替换值,那么哈希片对于同时分配多个键和值是很好的:

@grand_hash{ keys %new_hash } = values %new_hash;

在您的情况下,您可以调用一次子例程并存储结果,这样您就不必再次构造哈希。然后,您可以取消引用该散列是切片(或者您想使用它的任何地方:

my $new_hash = some_sub(...);
@grand_hash{ keys %$new_hash } = values %$new_hash;

是的,要取消引用哈希引用并获得键/值对列表,请将%{ ... }封装在生成哈希引用的表达式周围。

或者,从perl5.24开始,您可以使用后缀去引用语法sub()->%*

最新更新