Question

I have a hash of a hash (HoH) that I got from using select_allhashref on a mysql query. The format is perfect for what I want and I have two other HoH by similar means.

I want to eventually merge these HoH together and the only problem (I think) I have is that there is a key in the 'sub-hash' of one HoH that has the same name as one in another HoH. E.g.

my $statement1 = "select id, name, age, height from school_db";
my $school_hashref = $dbh->selectall_hashref($statement1, 1);

my $statement2 = "select id, name, address, post_code from address_db";    
my $address_hashref = $dbh->selectall_hashref($statement2, 1);

So when I dump the data I get results like so:

$VAR1 = {
          '57494' => {
                       'name' => 'John Smith',
                       'age' => '9',
                       'height' => '120'
                     }
        }
};
$VAR1 = {
          '57494' => {
                       'name' => 'Peter Smith',
                       'address' => '5 Cambridge Road',
                       'post_code' => 'CR5 0FS'
                     }
        }
};

(this is an example so might seem illogical to have different names, but I need it :) )

So I would like to rename 'name' to 'address_name' or such. Is this possible? I know you can do

$hashref->{$newkey} = delete $hashref->{$oldkey};

(edit: this is an example that I found online, but haven't tested.)

but I don't know how I would represent the 'id' part. Any ideas?

Was it helpful?

Solution

Not knowing the way that you are merging them together, the easiest solution might be to simply change the select statement to rename the column in your results. Rather than trying to manipulate the hash afterward.

my $statement2 = "select id, name as address_name, address, post_code from address_db";    
my $address_hashref = $dbh->selectall_hashref($statement2, 1);

If that is not a realistic option for you then a loop might be your best option

foreach (keys %{$address_hashref}) {
  $address_hashref->{$_}{$newkey} = delete $address_hashref->{$_}{$oldkey}
}

OTHER TIPS

You have do it with $hashref->{$newkey} = delete $hashref->{$oldkey}; because of the way hashes are implemented.

You can do it with hash of hashes too.

$hashref->{$key_id}{$newKey} = delete $hashref->{$key_id}{$oldKey};

The hash function is used to transform the key into the index (the hash) of an array element (the slot or bucket) where the corresponding value is to be sought.

Here's a simple example:

Our hash

{
   'a' => "apples",
   'b' => "oranges"
}

Let's define our hash function idx = h(key) and using the function on our keys above gives us:

h('a') = 02;
h('b') = 00;

How its stored in an array or bucket

idx  | value
00   | 'oranges'
01   | ''
02   | 'apples'
03   | ''
... and so on

Say we want they key of 'apples' to be 'c'. We cannot simply change the key to 'c', since the hash function always returns 02 for 'a', and will return something different for 'c'. So, if we want to change the key, we also have to move the value to the correct idx in the array/bucket.

Well, it might not be different, but that is a collision. Collisions are a special case that to be handled when implementing a hash.

For more info about on hashes:

http://en.wikipedia.org/wiki/Hash_table

How are hash tables implemented internally in popular languages?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top