Other Ways to Mess with Lists

But wait, that's not all. I've got a couple more functions that are useful for modifying and playing with lists: reverse, join, and map.

reverse

The reverse function takes each element of a list and turns it blue. Just kidding. reverse, as you might expect, reverses the order of the elements in the list:

@otherway = reverse @list;

Note that if you're sorting a list, or moving elements around using shift, unshift, push, or pop, you can use those methods to create reversed lists without having to reverse them using reverse (try to avoid moving array elements around more than you have to).

The reverse function also works with scalars, in which case it reverses the order of characters in a scalar. We'll come back to this in “Manipulating Strings,” later in this chapter.

join

The split function splits a string into a list. The join function does just the reverse: It combines list elements into a string, with any characters you want in between them. So, for example, if you had split a line of numbers into a list using this split command:

@list = split(' ', "1 2 3 4 5 6 7 8 9 10");

you could put them back into a string, with each number separated by a space, like this:

$string = join(' ', @list);

Or, you could separate each element with plus signs like this:

$string = join('+',@list);

Or, with no characters at all:

$string = join('',@list);

Let's look at a practical application of join. If you wanted to turn a list into an HTML list, you could use the following code:

print ''<ul><li>'', join(''</li><li>'', @list), ''</li></ul>'';

If you're concatenating a lot of strings, it's more efficient to use the join function than to use the . operator. Simply include an empty string as the separator, like this:

$new_string = join '', ('one', 'two', 'three', 'four'),

map

Earlier, you learned about grep, which is used to extract elements from a list for which an expression or pattern returns true. The map function operates in a similar way, except that instead of selecting particular elements from a list, map executes a given expression or block on each element in a list, and then collects the results of each expression into a new list.

For example, let's say you had a list of numbers, 1 to 10, and you wanted to build a list of the squares of all those numbers. You could use a foreach loop and push, like this:

foreach $num (1 .. 10) {
   push @squares, (@num**2);
}

The same operation in map might look like this:

@num = (1..10);
@squares = map { $_**2 }  @num;

Like grep, map takes each element in the list and assigns it to $_. Then, also like grep, it evaluates the expression. Unlike grep, it stores the result of that expression into the new list, regardless of whether it evaluates to true or not. Depending on how you write the expression, however, you can pass anything you want to the new list, including nothing, some value other than the original list item in $_, or even multiple items. Consider map to be a filter for each of the list items, in which the result of the filter can be anything you want it to be.The “filter” part of the map can be either a single expression or a block. If you're using a single expression, the value that gets returned at each turn of the map is simply the result of that expression. If you're using a block, the return value is the last expression that gets evaluated inside that block—so make sure you have an expression at the end that returns the value you're looking for. For example, here's a call to map that takes a list of numbers. It replaces any negative numbers with zero, and replaces all incidences of the number 5 with two numbers: 3 and 2. I've also formatted this version of map so that it's easier to read; there's no requirement for the code in either map or grep to be all on one line:

@final = map {
    if ($_ < 0) {
        0;
    }  elsif ($_ == 5) {
        (3,2);
    }  else { $_; }
} @nums;

This “last thing evaluated” behavior is actually a general rule for how blocks behave. You'll learn more about it when we get to subroutines on Day 11, “Creating and Using Subroutines.”

If you want to use an expression rather than a block, you need to include a comma between the two arguments to map. If you have an array of strings and you want to remove the line feeds from the end of each of the strings, you can use map as follows:

@new = map chomp, @old;

There's no rule that says the expression or block has to return a single, scalar value either. If an array is returned, then the entire array will be inserted in the new array where the original element was. Here's an example:

@old = ('one two', 'three four'),
@new = map { split " "; }  @old;
print scalar @new;

This snippet will print out the number 4 because the @new array now contains four items. Both of the original elements will be split into lists of two items, which will be inserted into the new list that the map function generates.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset