16.3. Transforming Items from a List with mapAnother common task is transforming items from a list. For example, suppose you have a list of numbers to format as money numbers for output, as with the subroutine &big_money (from Chapter 13). We don't want to modify the original data, and we need a modified copy of the list just for output. Here's one way to do that: my @data = (4.75, 1.5, 2, 1234, 6.9456, 12345678.9, 29.95); my @formatted_data; foreach (@data) { push @formatted_data, &big_money($_); } That looks similar in form to the example code used at the beginning of the section on grep, doesn't it? The replacement code resembles the first grep example: my @data = (4.75, 1.5, 2, 1234, 6.9456, 12345678.9, 29.95); my @formatted_data = map { &big_money($_) } @data; The map operator looks much like grep because it has the same kind of arguments: a block that uses $_ and a list of items to process. It operates in a similar way, evaluating the block once for each item in the list with $_ aliased to a different original list element each time. But the last expression of the block is used differently; instead of giving a Boolean value, the final value becomes part of the resulting list.[*] Any grep or map statement could be rewritten as a foreach loop pushing items onto a temporary array. But the shorter way is typically more efficient and convenient. Since the result of map or grep is a list, it can be passed directly to another function. Here we can print that list of formatted money numbers as an indented list under a heading:
print "The money numbers are:\n", map { sprintf("%25s\n", $_) } @formatted_data; We could have done that processing all at once without the temporary array @formatted_data: my @data = (4.75, 1.5, 2, 1234, 6.9456, 12345678.9, 29.95); print "The money numbers are:\n", map { sprintf("%25s\n", &big_money($_) ) } @data; As we saw with grep, there's a simpler syntax for map. If all you need for the selector is a simple expression (rather than a whole block), you can use that expression, followed by a comma, in place of the block: print "Some powers of two are:\n", map "\t" . ( 2 ** $_ ) . "\n", 0..15; |