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

I have got a hash that is for all intents and purposes backwards. Basically it is
my %hash = { ball1 => 'red', ball2 => 'blue', ball3 => 'red', };
and I need the logical equivalent of
%hash = { red => "ball1,ball3", blue => "ball2", }
I cannot just flop keys for values as I've got a duplicate of red. Any ideas?

Replies are listed 'Best First'.
Re: mildly tricky hash question
by davido (Cardinal) on Mar 30, 2004 at 08:33 UTC
    Try...
    my %reverse_hash; foreach my $key ( keys %hash ) { push @{$reverse_hash{$hash{$key}}, $key; }

    Or maybe a little clearer:

    my %reverse_hash; while ( my ( $key, $value ) = each %hash ) { push @{$reverse_hash{$value}}, $key; }


    Dave

      That would give him a hash of arrays - not what he's looking for. You could join all the arrays right after your loop, or you could change it to
      my %reverse_hash; foreach my $key ( keys %hash ) { $reverse_hash{$key}=$reverse_hash{$key} ? "$reverse_hash{$key},$hash{$key}" : $hash{$key}; }
        I'm getting an "undefined" error at the print statement when I use that bit of code. Warnings says that line 16 is using an uninitilized value..... what have I done wrong?
        #!/usr/bin/perl -w use strict; my $key; my %hash = ( ball1 => 'red', ball2 => 'blue', ball3 => 'red', ); # thanks to http://www.perlmonks.org/index.pl?node_id=340896 for this +block of code my %reverse_hash; foreach $key ( keys %hash ) { $reverse_hash{$key} = $reverse_hash{$key} ? "$reverse_hash{$key},$hash{$key}" : $hash{$key}; } print "$reverse_hash{red}\n";
Re: mildly tricky hash question
by Tomte (Priest) on Mar 30, 2004 at 08:56 UTC

    davidos code is way more elegant, if you employ matijas fix, but since I wrote it, here is a rather ugly solution:

    my %hash2 = (); my %unique = (); foreach my $test (grep(!$unique{$_}++, values %hash)) { $hash2{$test} .= join(",", grep({$hash{$_} eq $test ? hash{$_} : u +ndef} keys %hash)); }

    And since I was wondering, it isn't slower than davidos solution, the solutions seem to be equally efficient:

    regards,
    tomte


    Hlade's Law:

    If you have a difficult task, give it to a lazy person --
    they will find an easier way to do it.