http://www.perlmonks.org?node_id=1018185

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

Hello Monks!, I could use some help in trying to push multiple key-value pairs onto an existing hash.

#!/usr/bin/perl -w use strict; use Data::Dumper; #gene name and gene ID my %gene = ( "NCRNA00115" => "79854", "SAMD11" => "148398", "NOC2L" => "26155", "PLEKHN1" => "84069", "HES4" => "57801" ); # Let's add multiple key value pairs to the existing hash # push new data into a hash with $hash{key}=$value; # To add a second hash to the first, use @first{keys %second} = values + %second while(<DATA>){ chomp; my ($key, $value) = split; push @{$gene{$key}}, $value; } print Dumper(\%gene); __DATA__ ATAD3B 83858 ATAD3A 55210 SSU72 29101 SLC35E2 9906 GNB1 2782 TMEM52 339456

Replies are listed 'Best First'.
Re: pushing multiple key-value pairs into an existing hash
by choroba (Cardinal) on Feb 11, 2013 at 17:02 UTC
    If you want to add new key-value pairs one by one, you can use the scalar form:
    $gene{$key} = $value;
    The slice form can be used if you are inserting a hash into a hash, which is not the case here.
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ

      I don't want to add them one by one nor create another hash and combine the two. I was wondering if there is a way to take what's under __DATA__ and add each key-value pair dynamically?

        You said, ...push multiple key-value pairs onto an existing hash. Just to clarify, values (scalars) are pushed onto an array; you don't push onto a hash.

        The push in your while loop adds array references as values associated with keys, so you see a mix of data from the Dumper output (your push @{$gene{$key}}, $value; notation says treat the key's associated value as an array and push the contents of $value onto that array):

        $VAR1 = { 'HES4' => '57801', 'TMEM52' => [ '339456' ], 'SSU72' => [ '29101' ], 'GNB1' => [ '2782' ], 'PLEKHN1' => '84069', 'NCRNA00115' => '79854', 'ATAD3A' => [ '55210' ], 'ATAD3B' => [ '83858' ], 'SLC35E2' => [ '9906' ], 'SAMD11' => '148398', 'NOC2L' => '26155' };

        The [ ] notation indicates a list--each one having been generated by the push--so your hash now contains array references and non-reference values.

        choroba has shown you how to add the key-value pairs to an existing hash (which will overwrite an existing value, if the key already exsits):

        while(<DATA>){ chomp; my ($key, $value) = split; $gene{$key} = $value; # choroba's suggestion }

        Dumper output:

        $VAR1 = { 'HES4' => '57801', 'TMEM52' => '339456', 'SSU72' => '29101', 'GNB1' => '2782', 'PLEKHN1' => '84069', 'NCRNA00115' => '79854', 'ATAD3A' => '55210', 'ATAD3B' => '83858', 'SLC35E2' => '9906', 'SAMD11' => '148398', 'NOC2L' => '26155' };

        Is this what you wanted to achieve?

        I do not undestand. __DATA__ is a filehandle. There is no method to add a filehandle's content to a hash. In your example, though, you are using
        while (<DATA>) {
        which seems like iterating over the filehandle line by line. What exactly do you need? Why is adding the pairs one by one or creating a temporary hash not an option?
        لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ

        I was wondering if there is a way to take what's under __DATA__ and add each key-value pair dynamically?

        How would that be done statically?

        I don't want to add them one by one

        Why not?
Re: pushing multiple key-value pairs into an existing hash
by johngg (Canon) on Feb 12, 2013 at 00:38 UTC

    Adding the key/value pairs one at a time, as shown by Kenosis, is the most obvious and straightforward way to do this. However, you could process all of your new data into separate key and value arrays using split and map before updating your %gene hash in one go via a slice.

    $ perl -Mstrict -Mwarnings -MData::Dumper -e ' > my %gene = ( > NCRNA00115 => 79854, > SAMD11 => 148398, > N0C2l => 26155, > PLEKHN1 => 84069, > HES4 => 57801, > ); > print Data::Dumper->Dumpxs( [ \ %gene ], [ qw{ *gene } ] ); > > open my $newFH, q{<}, \ <<EOD or die qq{open: < HEREDOC: > $!\n}; > ATAD3B 83858 > ATAD3A 55210 > SSU72 29101 > SLC35E2 9906 > GNB1 2782 > TMEM52 339456 > EOD > > my( @newKeys, @newValues ); > my $iter = 0; > push @{ ++ $iter % 2 ? \ @newKeys : \ @newValues }, $_ for > map { split } > <$newFH>; > > @gene{ @newKeys } = @newValues; > print Data::Dumper->Dumpxs( [ \ %gene ], [ qw{ *gene } ] );' %gene = ( 'HES4' => 57801, 'N0C2l' => 26155, 'PLEKHN1' => 84069, 'NCRNA00115' => 79854, 'SAMD11' => 148398 ); %gene = ( 'HES4' => 57801, 'TMEM52' => '339456', 'SSU72' => '29101', 'GNB1' => '2782', 'PLEKHN1' => 84069, 'NCRNA00115' => 79854, 'ATAD3A' => '55210', 'N0C2l' => 26155, 'SLC35E2' => '9906', 'ATAD3B' => '83858', 'SAMD11' => 148398 ); $

    I hope this is of interest.

    Cheers,

    JohnGG