我猜您有一些返回哈希引用的子例程,并且您希望将所有这些键包含在更大的哈希中:
my $hash_ref = some_sub(...);
my $big_hash = { a => 1 };
您可以通过多种方式进行操作。在您的问题中,您似乎正试图通过取消引用返回值来内联。这可能是合理的。环绕符号或postfix dereference 可以做到这一点:
# 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()->%* );
还有许多其他方法可以合并哈希。 StackOverflow 上有How can I combine hashes in Perl?,perlfaq4 中也有How do I merge two hashes。
但是,还有另一件事需要考虑。简单地将两个哈希混合在一起以获得一个新的哈希可能会很昂贵。如果第一个哈希非常非常大怎么办?
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;