Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid

Help with better complex hash processing

by josephworkman (Novice)
on Sep 27, 2006 at 15:59 UTC ( #575178=perlquestion: print w/replies, xml ) Need Help??
josephworkman has asked for the wisdom of the Perl Monks concerning the following question:

I have a hash that looks like this:

$exception_report->{$node}{$exception}{$file}{$metric} = $value;

I have an extremely ugly method for printing this out. I have been reading a little about recursion and believe that would definitly help out here. Could you give me some pointers on how to properly print this out?

for my $node (keys %{$exception_report}) { print "Exceptions for $node:\n\n"; for my $exception (keys %{$exception_report->{$node}}) { for my $file (keys %{$exception_report->{$node}{$exception}}) +{ while ( my ($metric, $value) = each %{$exception_report->{ +$node}{$exception}{$file}} ) { print "\t$exception : ($file) $metric = $value\n"; } } } }

Replies are listed 'Best First'.
Re: Help with better complex hash processing
by philcrow (Priest) on Sep 27, 2006 at 16:14 UTC
    Turning your loop into recursion might look like this:
    #!/usr/bin/perl use strict; my $exception; $exception->{a}{b}{c}{d} = 4; walk_hash( $exception ); sub walk_hash { my $arg = shift; foreach my $key ( keys %{ $arg } ) { my $value = $arg->{ $key }; if ( ref( $value ) eq 'HASH' ) { walk_hash( $value ); } else { print "\t$key : $value\n"; } } }
    So in the sub, check the type of the value. If it's a hash, walk it, otherwise print the key:value. You can pass other things to the recursion if you need them, like the depth so you can alter indentation.


Re: Help with better complex hash processing
by jdporter (Canon) on Sep 27, 2006 at 16:24 UTC

    You're right, a general solution would involve recursion. I don't think you need it in this case, because your tree has a specific fixed depth. But here's a recursive solution anyway:

    sub tree_to_table { if ( ref $_[-1] ) { my $hr = pop; my @kv; tree_to_table( @_, @kv ) while @kv = each %$hr; } else { local($,,$\) = (',',"\n"); print map qq("$_"), @_ } } tree_to_table( $exception_report );
    We're building the house of the future together.
      That does EXACTLY what I was looking for! You ROCK!

      Phil - slick coding as well ;o)
Re: Help with better complex hash processing
by pbeckingham (Parson) on Sep 27, 2006 at 16:05 UTC

    YAML is good for this. Unless, of course, you need a specific format.

    use YAML; print Dump ($exception_report);

    pbeckingham - typist, perishable vertebrate.
      Yes unfortuantely I will need to actually print this out into a particular format. I plan on having different print outs based on what the user woudl like to sort on. I also plan on creating a csv file from this as well.
Re: Help with better complex hash processing
by YuckFoo (Abbot) on Sep 27, 2006 at 18:46 UTC
    If you just wanna get rid of the long series of dereferences that tend to uglify the code and cause much typing, save each step of dereference inside each loop.


    for my $nkey (keys %$exception_report) { my $node = $exception_report->{$nkey}; print "Exceptions for $nkey:\n\n"; for my $ekey (keys %$node) { my $exception = $node->{$ekey}; for my $fkey (keys %$exception) { my $file = $exception->{$fkey}; while ( my ($metric, $value) = each %$file) { print "\t$ekey : ($fkey) $metric = $value\n"; } } } }

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://575178]
Approved by chargrill
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others having an uproarious good time at the Monastery: (7)
As of 2018-04-23 12:46 GMT
Find Nodes?
    Voting Booth?