用不同的名称替换哈希键

时间:2012-02-01 19:56:06

标签: perl

  

可能重复:
  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',然后将其放回原始散列中。

3 个答案:

答案 0 :(得分:4)

这适用于任何1:1映射,即使某些键是相同的。这会将a切换为b(反之亦然):

my @new_keys = keys %hash;
y/ab/ba/ foreach @new_keys;
@hash{@new_keys} = delete @hash{keys %hash};

技巧是最后一行,它使用散列片同时替换所有键,因此冲突无关紧要。

编辑:基准(现在正在工作,感谢@EricStrom)

以下是@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} ;
}

可能有更短的版本,但这应该有用。