Modifying List Elements

You can always add and remove list, array, and hash elements using the methods I described on Days 4and 5. But sometimes the standard ways of adding and removing elements from lists can be awkward, hard to read, or inefficient. To help with modifying lists, Perl provides a number of built-in functions, including

  • push and pop: add and remove list elements from the end of a list.

  • shift and unshift: add and remove list elements from the start of a list.

  • splice: add or remove elements anywhere in a list.

push and pop

The push and pop functions allow you to add or remove elements from the end of a list, that is, it affects the highest index positions of that list. Both push and pop will be familiar functions if you've ever worked with stacks, where the notion is that the first element in is the last element out. If you haven't dealt with stacks before, envision one of those spring-loaded plate dispensers you sometimes see in cafeterias. You add plates to the dispenser (push them onto the stack), but the top plate is always the one you use first (pop them off of the stack). So it is with push and pop and arrays: pushing adds an element to the end of the list, and popping removes an element from the end of the list.

The push function takes two arguments: a list to be modified, and a list of elements to be added. The original list is modified in place, and push returns the number of elements in the newly modified list. So, for example, in morenames.pl from the previous section, we used this ugly bit of code to add a key to the @keys array:

$keys[++$#keys] = $n[0];

That same bit could be written with push like this:

push @keys, $n[0];

Fewer characters, yes, and also conceptually easier to figure out. Note that the second argument here is a scalar (which is then converted to a list of one element), but the second argument can itself be a list, which lets you combine multiple lists easily like this:

push @final, @list1;

The pop function does the reverse of push; it removes the last element from the list or array. The pop function takes one argument (the list to change), removes the last element, and returns that element:

$last = pop @array;

As with push, the list is modified in place and will have one less element after the pop. A convoluted way of moving elements from one array to another might look like this:

while (@old) {
   push @new, pop @old;
}

Note that with this bit of code the new array will be in the reverse order because the last element is the first to get pushed onto the new array. A better way of reversing a list is to use the reverse function instead, and a better way of moving one list to another is simply to use assignment. You could, however use this mechanism to modify each element as it gets passed from one element to the other:

while (@old) {
   push @new, 2 * pop @old;
}
						

shift and unshift

If push and pop add or remove elements from the end of the list, wouldn't it be nice to have functions that add or remove elements from the beginning of the list? No problem! shift and unshift do just that, shifting all elements one position up or down (or, as is more commonly envisioned with shift and unshift, left and right). As with push and pop, the list is modified in place.

The shift function takes a single argument, a list, and removes the first element from that list, moving all the remaining elements down (left) one position. It returns the element it removed. So, for example, this bit of code moves elements from one array to another, but this example doesn't reverse the list in the process:

 while (@old) {
   push @new, shift @old;
}

The unshift function is the beginning-of-list equivalent to push. It takes two arguments: the list to modify and the list to add. The new list contains the added elements, and then the old elements in the list, shifted as many places upward as there were elements added. The unshift function returns the number of elements in the new list:

$numusers = unshift @users, @newusers;

splice

push and pop modify the elements at the end of a list, shift and unshift do the same thing at the beginning. The splice function, however, is a much more general-purpose way to add, remove, or replace elements at any position inside the list. splice takes up to four arguments:

  • The array to be modified

  • The point (position, or offset) in that array to add or remove elements after

  • The number of elements to remove or replace. If this argument isn't included, splice will change every element from the offset forward.

  • The list of elements to add to the array, if any.

Let's start with removing elements from an array using splice. For each of these examples, let's assume a list of ten elements, 0 to 9:

@nums = 0 .. 9;

To remove elements 5, 6, and 7, you would use an offset of 5 and a length of 3. There's no list argument because we're not adding anything:

splice(@nums, 5, 3);  # results in (0,1,2,3,4,8,9)

To remove all elements from position 5 to the end of the list, leave off the length argument:

splice(@nums, 5);  # results in (0,1,2,3,4)

To replace elements, add a list of the elements to replace to the splice. For example, to replace elements 5, 6, and 7 with the elements "five", "six", and "seven", use this code:

splice(@nums, 5, 3, qw(five six seven)); # results in (0,1,2,3,4,
                                         # "five","six","seven",8,9)

Perl doesn't care whether you're removing the same number of elements as you're adding; it'll just add the elements in the list at the position given by the offset, and move all the other elements out of the way (or shrink the array to fit). So, for example, here's a call to splice to delete elements 5, 6, and 7, and add the word "missing" in their place:

splice(@nums, 5, 3, "missing"); # results in (0,1,2,3,4,"missing",8,9);

The new array, in that latter case, will contain only eight elements.

To add elements to the array without also removing elements, use 0 for the length. For example, here's a call to splice that adds a couple numbers after element 5:

splice(@nums, 5, 0, (5.1, 5.2, 5.3)); # results in  (0,1,2,3,4,5,5.1,5.2,5.3,6.7.8.9)

The splice function, as with the other list modification functions, modifies the list it's working on in place. It also returns a list of the elements it removed. You can use the latter feature to break up a list into several parts. For example, let's say you had a list of some number of elements, @rawlist, that you want broken up into two lists, @list1 and @list2. The first element in @rawlist is the number of elements that should be in @list1; the second final list will then contain any remaining elements. You might use code similar to this, where the first line extracts the appropriate elements from @rawlist and stored them in @list1, the second removes the first element (the number of elements) from @rawlist, and the third stores the remaining elements in @list2.

@list1 = splice(@rawlist, 1, $rawlist[0]);
shift @rawlist;
@list2 = @rawlist;

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

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