0

I have the following hash, and I want to add more values to it; however, doing it replaces the entire hash. I'm pretty sure this is a basic level question, but perl is an enigma wrapped in a mystery.

my %myNewHash = ();

%myNewHash = (
    lastName => $primaryInfo->{lastName},
    firstName => $primaryInfo->{firstName}
);

%myNewHash = (
    email => $primaryInfo->{email},
    phone => $primaryInfo->{phone}
);

At this point, %myNewHash only contains email/phone, lastName/firstName have been wiped out.

  • 2
    http://stackoverflow.com/questions/350018/how-can-i-combine-hashes-in-perl/350038#350038 – Mat Dec 24 '13 at 22:59
  • 2
    When you say `$foo = 1;` followed by `$foo = 2;`, what is the value of `$foo`? Hashes work the same way. – ThisSuitIsBlackNot Dec 24 '13 at 23:07
  • 1
    I know it's fashionable to bash Perl but it helps no one. All the languages that I can think of that have built-in hash support behave in the same way - assign to the hash as a whole and you change the contents as a whole - and I can't see a better way. If you had it your way then `%myNewHash = ()` would leave the hash untouched, so how could you empty it? – Borodin Dec 25 '13 at 00:52
  • 2
    At the command prompt type the following: `perldoc perlintro`. It's about a 20 minute read, and will unwrap the mystery leaving you only with the enigma... ;) – DavidO Dec 25 '13 at 01:03

5 Answers5

7

Existing hash (note that you don't need create an empty hash before assigning to it):

my %myNewHash = (
    lastName => $primaryInfo->{lastName},
    firstName => $primaryInfo->{firstName}
);

Since you're using the same keys in the new and the old hashes:

$myNewHash{$_} = $primaryInfo->{$_} for qw(email phone);

Or with a hash slice:

my @keys = qw(email phone);
@myNewHash{@keys} = @{ $primaryInfo }{@keys};

The key (pun intended) is that you assign to an individual element

$hash{key} = ...

instead of to the hash itself

%hash = ( ... );
ThisSuitIsBlackNot
  • 23,492
  • 9
  • 63
  • 110
3

Here's one way you can do it:

use strict;
use warnings;

my %myNewHash = (
    lastName  => $primaryInfo->{lastName},
    firstName => $primaryInfo->{firstName}
);

$myNewHash{email} =  $primaryInfo->{email};
$myNewHash{phone} =  $primaryInfo->{phone};

Or:

use strict;
use warnings;

my %myNewHash;
$myNewHash{lastName}  =  $primaryInfo->{lastName};
$myNewHash{firstName} =  $primaryInfo->{firstName}
$myNewHash{email}     =  $primaryInfo->{email};
$myNewHash{phone}     =  $primaryInfo->{phone};
Kenosis
  • 6,196
  • 1
  • 16
  • 16
3

Whenever you do:

%myNewHash = ...;

You're reinitializing the value of %myNewHash. This is what the = operator does. It's the same thing as:

my $var = "This is the first part of my sentence,";
my $var = " and this is the last part of my sentence."; # Reinitializing $var, not appending it

To get around this, you could do the following:

%myNewHash = ( %myNewHash, email => $primaryInfo->{email}, phone => $primaryInfo->{phone} );

In this context, the key/value pairs in %myNewHash are treated as an array, The other two key/value pairs are put into that array and assigned to %myNewHash as one big array. %myNewHash is reinitialized, but now contains the exiting key/value pairs it had before.

I personally wouldn't do this because it's not 100% clear what's going on. If you want to convert your hash reference into a hash, you can dereference it and do it all in a single shot:

my %myNewHash = %{ $primaryInfo };  # Easy to understand.

Or use a loop to pick off the few keys you want to transfer over:

for my $key ( qw( email phone ) } {
    $myNewHash{$key} = $primaryInfo->{$key};
}

I'm sure there's even a way to use map, but I can't think of it right off hand.

David W.
  • 105,218
  • 39
  • 216
  • 337
0

Try adding like this:

%myNewHash = (
    %myNewHash,
    email => $primaryInfo->{email},
    phone => $primaryInfo->{phone}
);
Ryan Kohn
  • 13,079
  • 14
  • 56
  • 81
0

I'd do this by "slicing" the hash. Put the sigil @ in front of the hash name (which indicates that you use a slice of the hash), provide the new keys within curly braces (which indicates you are referring to a hash and to its single entries) and then just assign the values for the new entries

@myNewHash{"email", "phone"} = ("name@domain.tld", "+122222222222");