SPUG: Pretty-Printing Nested Hashes?

Michael Wallendahl mwallend at spikus.com
Mon Sep 19 15:31:50 PDT 2005


Hello,

I'm wondering if anyone has a suggestions on a good algorithm to
'pretty-print' a nested hash in tabular form?

Take the following hash:

---BEGIN PERL---

#!perl

use strict;
use warnings;

my %h;

$h{one}->{First} = 'Bob';
$h{one}->{Last}  = 'Marley';
$h{two}->{First} = 'Sue Ellen';
$h{two}->{Last}  = 'Smith';

---END PERL---

Is there an easy way to print out the contents of %h in a tabular form
so that the width of each column is set to the largest element?   Like
this:

    First     Last 
    --------- ------
    Bob       Marley
    Sue Ellen Smith

In the past I've resorted to traversing the nested hash looking at each
element's value, saving the largest width away in a variable, and then
using printf statements. This quickly gets messy as the number of columns
increase.

For example, continuing on with perl:

---BEGIN PERL---

my $max_first = 5; # Length of column name 'First' as the min.
my $max_last  = 4; # Length of column name 'Last' as the min.
foreach my $user (keys %h) {
   my $len_f = length($h{$user}->{First});
   my $len_l = length($h{$user}->{Last });
   if ($len_f > $max_first) { $max_first = $len_f; }
   if ($len_l > $max_last ) { $max_last  = $len_l; }
}

print "Max length of First column: $max_first\n";
print "Max length of Last column : $max_last\n";

# print heading.
printf "%-*s %-*s\n",
    $max_first, 'First',
    $max_last , 'Last';

# print underlines for heading.
printf "%-*s %-*s\n",
    $max_first, '-' x $max_first,
    $max_last , '-' x $max_last;

# print out data.
foreach my $user (keys %h) {
    printf "%-*s %-*s\n",
        $max_first, $h{$user}->{First},
        $max_last , $h{$user}->{Last },

}

---END PERL---

Is there an easier way to do this that I'm just overlooking?
All those printf's just look messy to me.

Thanks,
-Mike




More information about the spug-list mailing list