use strict; my %hash = ( Downtown_Market => {Fruit => 1, More_fruit => 2, Even_more_fruit => 3}, Uptown_market => {More_fruit => 4, Fruit => 5}, East_market => {Even_more_fruit => 6}, ); my %columnLookup; my @columns; my $maxKeyLen = 0; # Build list of sub-keys for my $key (keys %hash) { $maxKeyLen = length $key if length $key > $maxKeyLen; for my $subKey (keys %{$hash{$key}}) { next if exists $columnLookup{$subKey}; $columnLookup{$subKey} = @columns; push @columns, $subKey; } } # Print the table for my $key (sort keys %hash) { printf "%-*s (", $maxKeyLen + 2, "$key :"; print join ', ', map {exists $hash{$key}{$_} ? $_ : ' ' x length $_} @columns; print ")\n"; }