可能重复:
How to replace a Perl hash key?
Changing keys in a “for ( keys %hash ) {}”-loop
我有一个类似以下的哈希
test0 => '1'
test1 => '2'
我想将其转换为
something0 => '1'
something1 => '2'
基本上,我想从散列中取出每个键,用'something'替换'test',然后将其放回原始散列中。
答案 0 :(得分:4)
这适用于任何1:1映射,即使某些键是相同的。这会将a切换为b(反之亦然):
my @new_keys = keys %hash;
y/ab/ba/ foreach @new_keys;
@hash{@new_keys} = delete @hash{keys %hash};
技巧是最后一行,它使用散列片同时替换所有键,因此冲突无关紧要。
以下是@ikegami发布的方法的基准(修正了错别字)以及上面的方法:
Rate ikegami_map ikegami_5.14 ikegami_for derobert
ikegami_map 38186/s -- -16% -19% -34%
ikegami_5.14 45547/s 19% -- -3% -22%
ikegami_for 47065/s 23% 3% -- -19%
derobert 58213/s 52% 28% 24% --
基准代码:
use List::MoreUtils qw(zip);
use Benchmark qw(cmpthese);
use v5.14;
use warnings qw(all);
our %hash = zip @{[ 'a'..'z' ]}, @{[ 1..26 ]};
%hash = map { y/a-z/n-za-m/r => $hash{$_} } keys(%hash);
cmpthese(-2, {
'derobert' => q{
my @new_keys = keys %hash;
y/a-z/n-za-m/ foreach @new_keys;
@hash{@new_keys} = delete @hash{keys %hash};
},
'ikegami_for' => q{
my %new_hash;
for my $orig (keys(%hash)) {
(my $new = $orig) =~ y/a-z/n-za-m/;
$new_hash{$new} = $hash{$orig};
}
%hash = %new_hash;
},
'ikegami_map' => q{
%hash = map {
(my $new = $_) =~ y/a-z/n-za-m/;
$new => $hash{$_}
} keys(%hash);
},
'ikegami_5.14' => q{
%hash = map { y/a-z/n-za-m/r => $hash{$_} } keys(%hash);
},
});
答案 1 :(得分:2)
使用for
(假设每个新密钥与每个现有密钥不同):
for my $orig (keys(%hash)) {
(my $new = $orig) =~ s/^test/something/;
$hash{$new} = delete($hash{$orig});
}
使用for
(可以安全地使用任何替换):
my %new_hash;
for my $orig (keys(%hash)) {
(my $new = $orig) =~ s/^test/something/;
$new_hash{$new} = $hash{$orig};
}
%hash = %new_hash;
使用map
(可以安全地使用任何替换):
%hash = map {
(my $new = $_) =~ s/^test/something/;
$new => $hash{$_}
} keys(%hash);
使用map
和5.14+(可以安全地使用任何替换):
%hash = map { s/^test/something/r => $hash{$_} } keys(%hash);
答案 2 :(得分:1)
my @keys = keys %hash ;
foreach my $key ( @keys ) {
my ( $newkey = $key ) =~ s/^test/something/ ;
$hash{$newkey} = $hash{$key} ;
delete $hash{$key} ;
}
可能有更短的版本,但这应该有用。