Robert's Perl Tutorial

http://www.sthomas.net/roberts-perl-tutorial.htm


Map

Map works the same way as grep , in that they both iterate over a list, and return a list. There are two important differences however:

As usual, an example will assist the penny in dropping, clear the fog and turn on the light (if not make my metaphors easier to understand):

@stuff=qw(flying gliding skiing dancing parties racing);

print "There are ",scalar(@stuff)," elements in \@stuff\n";
print join ":",@stuff,"\n";

@mapped  = map  /ing/, @stuff;
@grepped = grep /ing/, @stuff;

print "There are ",scalar(@stuff)," elements in \@stuff\n";
print join ":",@stuff,"\n";

print "There are ",scalar(@mapped)," elements in \@mapped\n";
print join ":",@mapped,"\n";

print "There are ",scalar(@grepped)," elements in \@grepped\n";
print join ":",@grepped,"\n";

You can see that @mapped is just a list of 1's. Notice that there are 5 ones whereas there are six elements in the original array, @stuff. This is because @mapped contains the true results of map -- in every case the expression /ing/ is successful, except for 'parties'.

In that case there the expression is false, so the result is discarded. Contrast this action with the grep function, which returns the actual value, but only if it is true. Try this:

@letters=(a,b,c,d,e);

@ords=map ord, @letters;
print join ":",@ords,"\n";

@chrs=map chr, @ords;   
print join ":",@chrs,"\n";

This uses the ord function to change each letter into its ASCII equivalent, then the chr function convert ASCII numbers to characters. If you change map to grep in the example above, you can see that nothing appears to happen. What is happening is that grep is trying the expression on each element, and if it succeeds (is true) it returns the element, not the result. The expression succeeds for each element, so each element is returned in turn. Another example:

@stuff=qw(flying gliding skiing dancing parties racing);

print join ":",@stuff,"\n";

@mapped  = map  { s/(^[gsp])/$1 x 2/e } @stuff;
@grepped = grep { s/(^[gsp])/$1 x 2/e } @stuff;

print join ":",@stuff,"\n";
print join ":",@mapped,"\n";
print join ":",@grepped,"\n";

Recapping on regex, what that does is match any element beginning with g, s or p, and replace it with the same element twice. The caret ^ forces a match at the beginning of the string, the [square brackets] denote a character class, and /e forces Perl to evaluate the RHS as an expression.

The output from this is a mixture of 1 and nothing for map , and a three-element array called @grepped from grep. Yet another example:

@mapped  = map  { chop } @stuff;
@grepped = grep { chop } @stuff;

The chop function removes the last character from a string, and returns it. So that's what you get back from ^ , the result of the expression. The grep function gives you the mangled remains of the original value.