tkguifan has asked for the wisdom of the Perl Monks concerning the following question:

my $input_hash_ref={ key1 => { some_field=>'value1', key=>'key1', alt_key=>'alt_key1' }, key2 => { some_field=>'value2', key=>'key2', alt_key=>'alt_key2' } }; my $output_hash_ref={ alt_key1 => { some_field=>'value1', key=>'key1', alt_key=>'alt_key1' }, alt_key2 => { some_field=>'value2', key=>'key2', alt_key=>'alt_key2' } };
  • Comment on How can one change the keys of a hash to an alternative set of keys?
  • Download Code

Replies are listed 'Best First'.
Re: How can one change the keys of a hash to an alternative set of keys?
by choroba (Cardinal) on Feb 04, 2015 at 21:52 UTC
    Use map. You might need to clone the hash if you don't want the input and output to share the inner structures.
    #! /usr/bin/perl use strict; use warnings; use Clone qw{ clone }; use Test::More tests => 2; my $input_hash_ref = { key1 => { some_field => 'value1', key => 'key1', alt_key => 'alt_key1' }, key2 => { some_field => 'value2', key => 'key2', alt_key => 'alt_key2' } }; my $expected_hash_ref={ alt_key1 => { some_field => 'value1', key => 'key1', alt_key => 'alt_key1' }, alt_key2 => { some_field => 'value2', key => 'key2', alt_key => 'alt_key2' }, }; my $output_hash_ref = { map { $input_hash_ref->{$_}{alt_key} => $input +_hash_ref->{$_} } keys %$input_hash_ref }; is_deeply($output_hash_ref, $expected_hash_ref, 'same inner hashes'); my $clone = clone($input_hash_ref); my $cloned_hash_ref = { map { $clone->{$_}{alt_key} => $clone->{$_} } keys %$clone }; is_deeply($cloned_hash_ref, $expected_hash_ref, 'cloned');
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
      This is an interesting response, because I also had problems with cloning my object. Currently I'm copying every field in the object by hand to the new object.
      sub clone { my $self=shift; my $clone=new Board; $clone->{rep}=$self->{rep}; $clone->{castling_rights}=$self->{castling_rights}; $clone->{half_move_clock}=$self->{half_move_clock}; $clone->{full_move_number}=$self->{full_move_number}; $clone->{ep_pos}=$self->{ep_pos}; $clone->{turn}=$self->{turn}; return $clone; }
        ... copying every field in the object by hand to the new object.

        Maybe (untested):

        use Scalar::Util qw(blessed); sub clone { my $self = shift; my $clone = blessed($self)->new or die "clone failed ($self)"; @{$clone}{keys %$self} = (values %$self); return $clone; }
        Of course, this is still essentially "copying by hand" with lotsa potential pitfalls.


        Give a man a fish:  <%-(-(-(-<

        It works only for the listed keys, and also, it only works if the hash is not deeper (no reference to a hash, array, or whatever).
        لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Re: How can one change the keys of a hash to an alternative set of keys?
by LanX (Saint) on Feb 04, 2015 at 22:14 UTC
    See each to iterate thru key/value pairs of a hash.

    Copy to new hash in loop with changed key.

    update

    To answer the tread title, you can't. Keys are immutable. They can be deleted or created but they can't be changed.

    Cheers Rolf

    PS: Je suis Charlie!

      Read also Do not use each.
      لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
        IIRC is each safe as long as you don't try to call any routines in the loop!

        Copying to a new hash is hardly a threat.

        Cheers Rolf

        PS: Je suis Charlie!

Re: How can one change the keys of a hash to an alternative set of keys?
by pme (Monsignor) on Feb 04, 2015 at 21:52 UTC
    $input_hash_ref->{alt_key1} = $input_hash_ref->{key1}; delete $input_hash_ref->{key1}; $input_hash_ref->{alt_key2} = $input_hash_ref->{key2}; delete $input_hash_ref->{key2};
    See delete
      No that's too dangerous!

      If old and new key set overlap you'll get ugly bugs.

      Defensive programming!!!

      Cheers Rolf

      PS: Je suis Charlie!

        This is a special case, because for some reason the two set of keys are guaranteed to uniquely identify the data structures behind them ( they are alternative descriptions of the same data ). They are constructed in such a way, that there can be no overlap ( in fact this takes quite a bit of effort, but ultimately it is done in a foolproof way ). It depends on the circumstances which set of keys is more convenient to access the data elements.
        This is true in general. But here I gave a specific comment on a specific question.
Re: How can one change the keys of a hash to an alternative set of keys? (slice+delete)
by tye (Sage) on Feb 05, 2015 at 22:54 UTC