Perl map Function



The Perl map function evaluates a block or an expression for each element of an array and returns a new array with the result of the evaluation. During the evaluation, it locally assigns the $_ variable to each element of the array.

The $_ is rather an alias of the array elements so you can use it to modify them, but this is not recommended because it can lead to unpredictable results.

The Perl map function transforms a list into a new one and this new list is returned by the function. No need to modify the input list.

Practically, it is a special case of a loop statement and it is very handy to apply some repetitive operations to all the elements of an array or a list.


Click Below to See the Best

Perl How-to Snippet Collection

and Save Hours of Surfing on Internet!


The map function is a particular case of a foreach statement but using map could make your code more succinct, clear or more perlish, if you want.

Please note the difference between the grep and map functions: while you can use grep to select elements from an array, you use map to transform the elements of an array. So keep in mind: grep to select, map to transform.

This short free tutorial will show you a few ways to use the Perl map function. But before proceeding with a few snippet code examples, let’s see the available syntax forms of this function:

map BLOCK LIST
map EXPR, LIST 

As in the case of other Perl functions, you can use or not the parentheses, sometimes it is a good choice to use them, especially when you need to avoid ambiguity or some precedence issues.

In the first syntax form, the Perl map function runs a block against each element of the LIST and returns another list with the result of the evaluation. A thing to remember is that inside the map block we have a list context - the result of the block becomes zero, one or more elements in the new list. The block may contain a number of statements separated by semi-colons, the statements being interpreted from left to right.

In the second syntax form, the Perl map function runs an expression on each element of the LIST and returns a new list with the result of evaluation.

Just as a note about this two map syntax forms, anytime you use a block, you introduce a new scope which adds some extra options and time to execute it. So try to use a block only when necessary. If you can use an expression instead of a block, this is preferable. Obviously, if you have a lot of things to do with each list element, avoiding the block is not an option.

Now, let’s see a few simple applications of the Perl map function.

Get a list with the squares of the first 10 positive integers


my @array = map $_** 2, 1..10;
print "@array\n";

# it outputs: 1 4 9 16 25 36 49 64 81 100

In this example the Perl map function was used with an expression: $_**2.

Each element of the 1..10 list is assigned in turn to $_ and the ** exponential operator is invoked to get the square of each number. Finally, the array is printed.

Apply a function to a list


# initialize an array
my @array = qw(this is a perl script);

@array = map { uc $_ } @array; 
print "@array\n";

# it displays: THIS IS A PERL SCRIPT

Here the Perl map function is used with a block. Each element of the array is assigned in turn to $_, the uc (uppercase) function is called with $_ as argument and the resulting list will be stored in the same array.

As a result, the map function will return all the elements converted in uppercase. In our example, the same array is used to get the result.

A map, grep and sort example


The following example shows you first how to get a bi-dimensional array (array of arrays) by using the Perl map function. See the code:

my @AOA = map { [ $_, (stat($_))[7] ] } glob('*');

# print the @AOA array
foreach my $item1 (@AOA){
  foreach my $item2 (@{$item1}){
    print "$item2 ";  
  }
  print "\n";
}

@AOA is an array that has as elements references to other arrays. Each sub-array will contain only two elements: the name of a file in the current directory and its size in bytes.

We’ll comment this code below:

  • the glob function is called in a list context with an wildcard asterisk character as argument, so it returns a list with all the filenames from the current directory
  • each element of the list returned by the glob function is assigned in turn to $_
  • {} are the block curly brackets
  • [] makes a new anonymous array and returns a reference to it:
    • the first element of the anonymous array is the value stored in $_ (i.e. the filename)
    • the second element is the size in bytes of the file – this is obtained by calling stat($_)[7] where $_ is the name of the file; the stat function returns a 13-element list, and the element with the index 7 means the size of the file in bytes
The Perl map function will return the references of the sub-arrays in the @AOA array.

Finally, a nested foreach is used to print the @AoA array.

Here’s a sample output from my Windows machine:

cities.txt 144
Colors1 18
Colors2 25
customers.txt 115

If you want to get these lines in the size ascending order, you can use the sort function and modify the previous code as in the following example:

my @AOA = sort { $a->[1] <=> $b->[1] } 
          map { [ $_, (stat($_))[7] ] } 
	  glob('*');

The array of arrays returned by the Perl map function is sorted in an ascending order by the element of index 1 of the sub-array (the <=> is the numerical comparison operator and $a and $b are the two special variables used by the sort function).

If you need to filter the resulting list, you can insert a grep function before the map function, where you can implement any condition you want. In the example below, we'll look for the files that have the size smaller than 100 bytes:

my @AOA = sort { $a->[1] <=> $b->[1] } 
          grep { $_->[1] < 100 }
          map { [ $_, (stat($_))[7] ] } 
	  glob('*');

This code is executed from right to left: glob, map, grep and sort and all the functions are invoked in a list context.


Using map to read data from a csv file


A csv file is a comma delimited text data file and ".csv" is its extension. An example of such a file is shown below:

Persons.csv

John,Silva,25,blue
Mary,Brown,32,brown
Paul,Williams,52,green

where the raw structure is as follows:

firstname,lastname,age,eyecolor

We intend to read this file and create a bi-dimensional array @AOA with the records of the file. Each element of the array is a reference to a sub-array that has as elements the items from the raw file.

Here’s the code:

open FILE, "persons.csv" or die $!;

my @AOA = map { chomp; [split /,/]; } ;

# print the @AOA array
foreach my $item1 (@AOA){
  foreach my $item2 (@{$item1}){
    print "$item2 ";  
  }
  print "\n";
}

The output is as follows:

John Silva 25 blue
Mary Brown 32 brown
Paul Williams 52 green

In this example the Perl map function is used with a block. Because the map function provides a list context, the file will be read once in a list of records.

Inside the map block:

  • each record from the list will be assigned in turn to $_
  • the chomp function will remove the trailing newline from $_
  • the split function will split the record of the file using the ',' delimiter, returning an anonymous array having as elements the fields of the record
  • [] returns a reference to the new anonymous array returned by the split function
The Perl map function returns the list with the array references in the @AOA array.

Finally, a nested foreach is used o print the @AOA array.

To test this script, you need to create the csv file yourself and put it in your current directory from where you run the script.

Make a hash out of a delimited string


See the next snippet for an example:

my $str = '1:one,2:two,3:three,4:four';
my %hash = map { split /:/, $_ } split /,/, $str;

# print the hash
while ( my ($key, $val) = each %hash ) {
  print "$key->$val\n";
}

This code produces the following output:

4->four
1->one
3->three
2->two

The second split function will split the string into a list using the comma delimiter; if we print the list elements, we’ll have something like this:

my @array = split /,/, $str;
print "@array\n";
# it displays: 1:one 2:two 3:three 4:four

Here we stored the list into an array and we printed the elements of the array separated by space (if you print an array enclosed with double quotes, the array will be interpolated and its elements will be printed separated by a space character).

Now, let's go back to our initial code. Inside the map block:

  • each element of the above list will be assigned in turn to $_
  • the value contained by $_ will be split again into a two element list using the ':' delimiter.
Because the list returned by the Perl map function will be assigned to a hash, the elements of the list will be grouped in (key, value) pairs.

Finally we printed the hash: the each function will return a (key, value) pair one at a time in a while loop and the print function will display the hash element.

How to use map to find the union of two arrays


To see this topic click here to watch a video on youtube where you'll find a complete example.


Please click here to download the Perl map script with all the above examples included.

Exercises


Through these exercises you have the opportunity to try yourself to write some script code where you can use the Perl map function. These exercises are completely covered in my Perl Functions for List Data where I show you how to play with this important function in detail.

1. Given the following hash:
my %hash = (
  tulip1 => 'red', petunia => 'purple', pansy => 'pink',
  rose1 => 'red', snowdrop => 'white', tulip2 => 'yellow',
  rose2 => 'yellow', rose3 => 'white', rose4 => 'pink',
  orchid1 => 'white', orchid2 => 'pink'
);
write a short code which returns a list with all the flowers that have white color. The list contains (snowdrop,rose,orchid) – you need to remove all the digits (if any) at the end of the flower name.
2. Given the following arrays:
my @A = (1, 2, 3, 5, 7, 23, 8, 14, 95, 19);
my @B = (3, 14, 6, 22, 88, 19, 100);
use map to get the union of the two arrays in a numerical ascending order.
3. Given the following array of arrays (@AoA):
my @AoA = ( 
  ['a1', 'b1', 'c1'],
  ['a2', 'b2', 'c2'],
);
use map to print the @AoA array as:
a1 b1 c1
a2 b2 c2
4. Given the following array of hashes (@AoH):
my @AoH = ( 
  { name => 'John', age => '21' },
  { name => 'Paul', age => '35' },
);
use map to print the @AoH array as:
John is 21 years old.
Paul is 35 years old.
5. Given the following hash of arrays (%HoA):
my %HoA = (
    colors => ['blue', 'white', 'red', 'green'],
    shapes => ['square', 'triangle', 'circle',],
);
use map to print the %HoA hash as:
shapes => square triangle circle
colors => blue white red green
6. Given the following hash of hashes (%HoH):
my %HoH = ( 
  1 => { color => 'yellow', width => 250, height => 120 },
  2 => { color => 'blue', width => 125, height => 320 },
  3 => { color => 'green', width => 25, height => 420 },
  4 => { color => 'red', width => 75, height => 12 },
);
use map to print the colors and widths as follows:
blue green red yellow
25 75 125 250


A-N-Y-O-N-E Can Learn and Master Perl!
And That Includes YOU!


Check these how-to tutorial eBooks (PDF format):


Table of Contents:

A Perl Script
Install Perl
Running Perl
Perl Data Types
Perl Variables
Perl Operators
Perl Lists
Perl Arrays
    Array Size
    Array Length
Perl Hashes
Perl Statements
    Perl if
    Perl unless
    Perl switch
    Perl while
    Perl do-while
    Perl until
    Perl do-until
    Perl for
    Perl foreach
Built-in Perl Functions
    Functions by Category
        String Functions
        Regular Expressions and Pattern Matching
        List Functions
        Array Functions
        Hash Functions
        Miscellaneous Functions
    Functions in alphabetical order
        chomp
        chop
        chr
        crypt
        defined
        delete
        each
        exists
        grep
        hex
        index
        join
        keys
        lc
        lcfirst
        length
        map (more)
        oct
        ord
        pack
        pop
        push
        q
        qq
        qw
        reverse
        rindex
        scalar
        shift
        sort
        splice
        split
        sprintf
        substr
        tr
        uc
        ucfirst
        undef
        unpack
        unshift
        values

return from Perl map function to Perl Basics



Would you like to create your own website like this one?
Hit the Alarm Clock!

Site Build It!