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

Hi all, I am very new to perl, actually just start handling hash, here is a problem I'd really need some help:

Basically I have two hashes. Hash1 has keys and values, for each value, it contains elements separated by ",". By splitting each of the value, the elements would be keys that can be found in the Hash2. What I want is to obtain the values in the Hash2 to be assigned to each of the corresponding keys in Hash1.

For example

%Hash1=(

'key1', 'val1,val2',

'key2', 'val3')

for each value in Hash1, it can be split by ",", then val1 and val2 are individual keys can be found in Hash2, and val1 as key in Hash2 has values (val5,val6, val7), val2 as key in Hash2 has values (val8 and val9) and so on. e.g.

%Hash2=(

'val1','val5,val6,val7',

'val2','val8,val9',

'val3','val3')

I would like to obtain a result as:

%newhash=('key1','val5,val6,val7,val8,val9',

'key2','val3')

that is that the keys in Hash1 have all corresponding values in Hash2

my problem is that I cannot put values for val1 and val2 together for key1.

Any suggestions are greatly appreciated.

  • Comment on how to use the values of the first hash to be the keys for the second hash

Replies are listed 'Best First'.
Re: how to use the values of the first hash to be the keys for the second hash
by choroba (Cardinal) on Sep 07, 2012 at 14:33 UTC
    Can you show the script? You probably assign istead of pushing.

    Update: Or, you can use map:

    #!/usr/bin/perl use warnings; use strict; use Data::Dumper; my %hash1 = (key1 => [qw(val1 val2)], key2 => ['val3'], ); my %hash2 = (val1 => [qw(val5 val6 val7)], val2 => [qw(val8 val9)], val3 => ['val3'], ); print Dumper { map { $_ => [ map @{ $hash2{$_} } , @{ $hash1{$_} } ] } keys %hash1 };
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ

      Thank you so much.

      Just I don't know how to print the result as the normal tab delimited table. Sorry for these newbie's questions.Really appreciate your help.

        You can use each to iterate over the hash:
        #!/usr/bin/perl use warnings; use strict; my %hash1 = (key1 => [qw(val1 val2)], key2 => ['val3'], ); my %hash2 = (val1 => [qw(val5 val6 val7)], val2 => [qw(val8 val9)], val3 => ['val3'], ); my %result = (map { $_ => [ map @{ $hash2{$_} } , @{ $hash1{$_} } ] } keys %hash1); while (my ($k, $v) = each %result) { print $k, " @$v\n"; }
        لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
        and, since value's of my hash tables are separated by ",", how can I do map by splitting values in hash1 by ","?
Re: how to use the values of the first hash to be the keys for the second hash
by BrowserUk (Patriarch) on Sep 07, 2012 at 20:10 UTC

    Jeez! People do love to change the question to suit their answer. Try this:

    #! perl -slw use strict; use Data::Dump qw[ pp ]; my %hash1 = ( 'key1', 'val1,val2', 'key2', 'val3' ); my %hash2=( 'val1','val5,val6,val7', 'val2','val8,val9', 'val3','val3' ); my %newhash = map { $_ => join ',', @hash2{ split ',', $hash1{ $_ } }; } keys %hash1; pp \%newhash; __END__ C:\test>junk { key1 => "val5,val6,val7,val8,val9", key2 => "val3" }

    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

    RIP Neil Armstrong

    p
      People do love to change the question to suit their answer.
      That was the author who changed the OP. Before the change, the structure of the hashes was not clear at all.
      لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ

        choroba was right that my original question was not clear. Thank you both for helping me on this, I really appreciate your help indeed. here is the code based on what I learned from here:

        my $hash1=shift; open (my $fh1, "<",$hash1) or die "$!"; my %h1=(); while (<$fh1>) { chomp; my ($k1,$v1)=split /\t/; $h1{$k1}=$v1; } my $hash2=shift; open (my $fh2, "<",$hash2) or die "$!"; my %h2=(); while (<$fh2>) { chomp; my ($k2,$v2)=split /\t/; $h2{$k2}=$v2; } my %combined_hash = map { $_ => join ',', map split(/,/, $h2{$_}), split /,/, $h1{$_} } keys %h1; while (my ($k, $v) = each %combined_hash) { print "$k\t$v\n"; }

      thank you so much.

      when I tried to print the %newhash:

      #!/usr/bin/perl use warnings; use strict; use Data::Dump qw[ pp ]; #subroutine: read in hash tables my $hash1=shift; open (my $fh1, "<",$hash1) or die "$!"; my %h1=(); while (<$fh1>) { chomp; my ($k1,$v1)=split /\t/; $h1{$k1}=$v1; } my $hash2=shift; open (my $fh2, "<",$hash2) or die "$!"; my %h2=(); while (<$fh2>) { chomp; my ($k2,$v2)=split /\t/; $h2{$k2}=$v2; } my %newhash = map { $_ => join ',', @h2{ split ',', $h1{ $_ } }; } keys %h1; while (my ($k, $v) = each %newhash) { print $k, "\t@{$newhash{$k}}\n"; }

      it says "Can't use string ("val3") as an ARRAY ref while "strict refs" in use at line 34, <$fh2> line 3.'"

      could you explain to me why?,/p>

        Have you tried dumping the two input hashes after you've populated them?


        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.

        RIP Neil Armstrong

Re: how to use the values of the first hash to be the keys for the second hash
by philiprbrenan (Monk) on Sep 07, 2012 at 14:44 UTC

    Do you mean something like this?

    use feature ":5.14"; use warnings FATAL => qw(all); use strict; use Data::Dump qw(dump pp); my %a = qw(key1 val1 key2 val2 key3 val3); my %b = qw(val1 val5 val2 val6 val3 val7 val4 val8); my %c = %{{map {($_, $b{$a{$_}})} keys %a}}; pp(\%c)

    Produces:

    { key1 => "val5", key2 => "val6", key3 => "val7" }

      thank you guys for the quick reply

      for my hash1

      I have "key1" with values "val1, val2",

      "key2 withs value "val3".

      each of the value in hash1, is key in hash2:

      for example: "val1" in hash1 has values "val4, val5, val6" in hash2; and so on.

      What I need is to generate a hash to combine the first two hashes, something like the following:

      "key1" with values "val4,val5,val6,val7, val8";

      "key2" with value "val3".

        use feature ":5.14"; use warnings FATAL => qw(all); use strict; use Data::Dump qw(dump pp); my %h1 = (key1=>[qw(1.1.1 1.1.2 1.1.3)], key2=>[qw(1.2.1 1.2.2 1.2.3)] +); my %h2 = (key1=>[qw(2.1.1 2.1.2 2.1.3)], key2=>[qw(2.2.1 2.2.2 2.2.3)] +); my %c; for my $h(\%h1, \%h2) {push @{$c{$_}}, $h->{$_} for keys %$h; } pp(\%c)

        Produces:

        { key1 => [["1.1.1", "1.1.2", "1.1.3"], ["2.1.1", "2.1.2", "2.1.3"]], key2 => [["1.2.1", "1.2.2", "1.2.3"], ["2.2.1", "2.2.2", "2.2.3"]], }