in reply to Modifying the keys in a hash

Hi, You could treat the hash as an array and modify the key with something like:
%hash = map { s/^key1$/new_key2/; $_; } %hash;
However, I'm not sure I would recommend it, as I don't think it makes what you are trying to do any clearer, and it has the potential to modify values that also match the regex!

Replies are listed 'Best First'.
Re^2: Modifying the keys in a hash
by merlyn (Sage) on Feb 23, 2007 at 15:12 UTC
    ... map { s/^key1$/new_key2/; $_; } ...
    In general, this idiom is a bad idea, because the value of $_ is a reference to the original data. So not only do you have a new value on your output, you have also edited the values on the input (if possible)!

    If you want to make changes like that, make a local copy of $_:

    ... map { local $_ = $_; s/^key1$/new_key2/; $_; } ...
      That's interesting - I wondered if that could be used to modify the hash key without creating a copy of the whole hash so tried:
      use Data::Dump qw(dump); my %hash = ( key1 => 'Value1', key2 => 'Value2', key3 => 'Value3', ); print "old hash is " . dump(\%hash) ."\n"; map { s/2/_two/; } %hash; print "new hash is " . dump(\%hash) ."\n"; # output is: # old hash is { key1 => "Value1", key2 => "Value2", key3 => "Value3" } # new hash is { key1 => "Value1", key2 => "Value_two", key3 => "Value3 +" }
      How come 'Value2' is changed to 'Value_two', but 'key2' is unchanged?

      (Note: I wasn't suggesting that this method should be used for modifying a hash key, but was trying to rise to the challenge of suggesting another method other than copy and delete!)

        How come 'Value2' is changed to 'Value_two', but 'key2' is unchanged?
        Because the keys aren't dealt out into $_ in the same way as the values. Consider:
        qwurx [shmem] 15:35 ~ > perl -MDevel::Peek -e '%hash = qw(a 1 b 2 c 3) +; for(%hash){print STDERR "$_: ";Dump $_; s/b/d/;} print "$_ => $hash +{$_}\n" for sort keys %hash' c: SV = PVIV(0x8168b10) at 0x8166b44 REFCNT = 2 FLAGS = (POK,FAKE,READONLY,pPOK) IV = -289776295 PV = 0x8187928 "c" CUR = 1 LEN = 0 3: SV = PV(0x8167ae8) at 0x8167894 REFCNT = 2 FLAGS = (POK,pPOK) PV = 0x818f380 "3"\0 CUR = 1 LEN = 4 a: SV = PVIV(0x8168b20) at 0x8166cf4 REFCNT = 2 FLAGS = (POK,FAKE,READONLY,pPOK) IV = -902917054 PV = 0x817be80 "a" CUR = 1 LEN = 0 1: SV = PV(0x8167b00) at 0x8166c28 REFCNT = 2 FLAGS = (POK,pPOK) PV = 0x817ecb0 "1"\0 CUR = 1 LEN = 4 b: SV = PVIV(0x8168b50) at 0x818dfd8 REFCNT = 2 FLAGS = (POK,FAKE,READONLY,pPOK) IV = 14385563 PV = 0x81876b0 "b" CUR = 1 LEN = 0 2: SV = PV(0x8167ba8) at 0x8166d90 REFCNT = 2 FLAGS = (POK,pPOK) PV = 0x81866b0 "2"\0 CUR = 1 LEN = 4 a => 1 b => 2 c => 3

        The flags for a hash key are (POK,FAKE,READONLY,pPOK), for values they are (POK,pPOK). Which means you manipulate the actual content modifying a value, but you're operating on fake variables modifying the keys.

        --shmem

        _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                      /\_¯/(q    /
        ----------------------------  \__(m.====·.(_("always off the crowd"))."·
        ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
Re^2: Modifying the keys in a hash
by shmem (Chancellor) on Feb 23, 2007 at 14:37 UTC
    You could treat the hash as an array and modify the key

    Sure you could, but why?

    Re-construct the entire hash to modify just one key? That's feasible, but only for small hashes, since you are duplicating all keys and values of the hash into a temporary list. Pretty much overhead.

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}