[ Team LiB ] Previous Section Next Section

Recipe 5.6 Printing a Hash

5.6.1 Problem

You want to print a hash, but neither print "%hash" nor print %hash does what you want; the first is a literal, while the second just has the keys and values all scrunched together.

5.6.2 Solution

One of several approaches is to iterate over every key-value pair in the hash using Recipe 5.5 and print them:

while ( ($k,$v) = each %hash ) {
    print "$k => $v\n";
}

Or use map to generate a list of strings:

print map { "$_ => $hash{$_}\n" } keys %hash;

Or use the interpolation trick from Recipe 1.15 to interpolate the hash as a list:

print "@{[ %hash ]}\n";

Or use a temporary array variable to hold the hash, and then print that:

{
    my @temp = %hash;
    print "@temp";
}

5.6.3 Discussion

The methods differ in the degree that their output is customizable (in order and formatting) and in their efficiency.

The first method, iterating over the hash, is flexible and space-efficient. You can format the output as you like it, and it requires only two scalar variables: the current key and value. You can print the hash in key order (at the cost of building a list of sorted keys) if you use a foreach loop:

foreach $k (sort keys %hash) {
    print "$k => $hash{$k}\n";
}

The map function is just as flexible. You can still process the list in any order by sorting the keys. You can customize the output to your heart's content. But it builds up a list of strings like "KEY =>VALUE\n" to pass to print.

The last two methods are interpolation tricks. By treating the hash as a list, you can't predict or control the output order of key-value pairs. Furthermore, the output will consist of a list of keys and values, each separated by whatever string that $" happens to hold. You can't put newlines between pairs or "=>" within them, as we could with the other methods.

Another solution is to print the hash in a list context after temporarily localizing the $, variable to a space.

{
    local $, = " ";
    print %hash;
}

This is like the solution of copying to an array and then doing double-quote interpolation on that array, except it doesn't duplicate the contents of the hash twice more than you need (i.e., once for the array, then again for the string).

The Dumpvalue module, described in Recipe 11.11, can provide for pretty printed output displays, plus much more. For example:

use Dumpvalue;
$dumper = Dumpvalue->new;
$dumper->dumpValue(\%food_color);
'Apple' => 'red'
'Banana' => 'yellow'
'Carrot' => 'orange'
'Lemon' => 'yellow'

5.6.4 See Also

The $" and $, variables in perlvar(1) and in the "Per-Filehandle Variables" section of Chapter 28 of Programming Perl; the foreach, map, keys, sort, and each functions in perlfunc(1) and Chapter 29 of Programming Perl; we give a technique for interpolating into strings in Recipe 1.15; we discuss the techniques for hash traversal in Recipe 5.5

    [ Team LiB ] Previous Section Next Section