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

I have a big hash. Some of the values in the hash are the same how do I do to add all the keys for the values that are the same?

An example of what I mean would be:

%hash=(10=>1, 20=>2, 30=>1 40=>2);

After the procedure it should look:

%hash=(40=>1, 60=>2);

If I want to check if a key exist in a hash I do..

if (exists ($hash{$key})) { do.. }

This i very confusing to me. To $hash{$key} should be the same as the value. Could someone explain.

And how do I check if a value exists? I can not reverse the hash since it has many of the same values.

Thank you for your help.

Code tags added by GrandFather

Replies are listed 'Best First'.
Re: Confusion due to hash
by McDarren (Abbot) on Jan 31, 2006 at 00:26 UTC
    Okay, well the approach I would take is to create a new hash where the keys/values of your existing hash are reversed.

    You simply iterate through you existing hash and build up the new hash as you go, like so:

    foreach my $key (keys %hash) { $newhash{$hash{$key}} += $key; }
    Using your sample data, that will give you something that looks like:
    %newhash = ( '1' => 40, '2' => 60 );
    Does this help?

    Cheers,
    Darren :)

Re: Confusion due to hash
by GrandFather (Saint) on Jan 31, 2006 at 00:57 UTC

    I'm not quite sure where you are going with this, but it seems to me that you need two hashes:

    use strict; use warnings; use Data::Dumper; my %hash= (10=>1, 20=>2, 30=>1, 40=>2); my %rhash; map {$rhash{$hash{$_}} += $_} keys %hash; print Dumper (\%hash); print Dumper (\%rhash);

    Prints:

    $VAR1 = '%hash'; $VAR2 = { '40' => 2, '30' => 1, '10' => 1, '20' => 2 }; $VAR1 = '%rhash'; $VAR2 = { '1' => 40, '2' => 60 };

    DWIM is Perl's answer to Gödel
      reverse is useful to get the output in the desired format:
      use strict; use warnings; use Data::Dumper; my %input = (10=>1, 20=>2, 30=>1, 40=>2); my %output; map { $output{ $input{ $_ } } += $_ } keys %input; %output = reverse %output; print Dumper \%output;
      Prints:
      $VAR1 = { '60' => '2', '40' => '1' };
      Update: I paid to much attention to the requested output, and not enough to the note that he couldn't reverse the hash

        Except that OP says

        And how do I check if a value exists? I can not reverse the hash since it has many of the same values.

        in which case leaving %rhash in its original form allows the lookup that OP wants - no reversing required.


        DWIM is Perl's answer to Gödel
Re: Confusion due to hash
by martin (Friar) on Jan 31, 2006 at 03:21 UTC
    You did not state what should happen in a case like this:
    %hash = (10 => 1, 20 => 1, 30 => 2);

    Can you elaborate?