Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister

Reorganising a Hash for Output

by arunhorne (Pilgrim)
on May 07, 2002 at 13:06 UTC ( #164621=perlquestion: print w/replies, xml ) Need Help??

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

Hi all,

I have a hash in the following format (the notation is my own brand ;) but what it shows is a scalar on the left mapping to an array of values (the right hand side is of course a ref to the actual array):

1 -> @{a, b, c} 2 -> @{d, e, f} 3 -> @{g, h, i}

My first task i needed to do to this hash was print out each key, with each corresponding value on a new line, thus:

1, a 1, b ... 3, h 3, i

This was straightforward. My new requirement is to print in the form:

a, 1 b, 1 c, 1 ... g, 3 h, 3 i, 3

As an extra caveat I also want to make sure the output is ordered by the output, i.e. as it is in the above, a before b etc.

Has anyone got any nice perl ways of doing this or am I going to have to go for brute force set of nested foreach statements? I certainly have no idea as to making the output ordered!

By the way I still need to maintain the hash in its original form as the first output method (the one I have working) is still required.

Thanks, Arun

Replies are listed 'Best First'.
Re: Reorganising a Hash for Output
by graff (Chancellor) on May 07, 2002 at 13:22 UTC
    Since you are already able to do this form of output:
    1, a 1, b ... 3, h 3, i

    just push these same items onto an array while you're doing this. Then, when you're done with this loop, print the sorted array. E.g. if the above form of output is done in a loop with a statement like this:
    print "$key, $value\n";
    add this line right after the print statement:
    push( @secondOutput, "$value, $key" );
    Then, after that loop is done, just do:
    print join( "\n", sort( @secondOutput ), "" );
    (the "" after the sort is so that join() will add a linefeed after the last array element).
      Thanks graff... I like your thinking and it worked great. Cheers :D
Re: Reorganising a Hash for Output
by talexb (Chancellor) on May 07, 2002 at 13:13 UTC
    Something like
    foreach my $HashKey ( keys %Hash ) { foreach ( sort @{ $Hash{ $HashKey } } ) { print "$HashKey: $_\n"; } }
    should do the trick. I haven't tested this code.

    --t. alex

    "Nyahhh (munch, munch) What's up, Doc?" --Bugs Bunny

Re: Reorganising a Hash for Output
by bmcatt (Friar) on May 07, 2002 at 13:30 UTC
    Try this...
    #!/usr/bin/perl -w use strict; my %x = ( 1 => [qw(d e f)], 2 => [qw(a b c)], 3 => [qw(g h i)] ); my %rev = map { my $key=$_; map { $_=>$key} @{$x{$key}} } keys %x; print "$_ -> $rev{$_}\n" foreach sort keys %rev;

    The trick (imho) is to build the "reverse" hash first and then deal with sorting / outputing that after the fact.

    Btw, I'd suggest not using non-standard notation, even if it's comfortable for you. It'll (potentially) make things harder when you're trying to show other people.

      The trick (imho) is to build the "reverse" hash first

      Wrong. What if you have duplicate values in your arrays? You will loose a whole lot of values as they can't exist as "duplicate" hash keys. Oops

      my %x = ( 1 => [qw( o o p s )], 2 => [qw( j u s t )], 3 => [qw( a n o t h e r )], 4 => [qw( h a s h )], 5 => [qw( e r r o r )], 6 => [qw( j u s t a n o t h e r p e r l h a c k e r , )] ); my %rev = map { my $key=$_; map { $_=>$key} @{$x{$key}} } keys %x; print "$_ -> $rev{$_}\n" foreach sort keys %rev;

      What happened to all the values for keys 1-5?




Re: Reorganising a Hash for Output
by demerphq (Chancellor) on May 07, 2002 at 15:32 UTC
    It sounds to me like you would benefit by working through perlfaq4 -- Data Manipulation. Theres some excellent code snippets in there for all manner of data structure issues, including this one (How do I look up a hash element by value?)

    Yves / DeMerphq
    Writing a good benchmark isnt as easy as it might look.

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://164621]
Approved by broquaint
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (3)
As of 2022-05-18 17:20 GMT
Find Nodes?
    Voting Booth?
    Do you prefer to work remotely?

    Results (71 votes). Check out past polls.