| |
List Processing, Slices, and @ARGV
Page history last edited by dmlond 3 yrs ago
- What is a List: Lists in Perl are ordered sets of scalars. They can be explicitly assigned or referenced to a variable, created deNovo when they are needed, or implicitly created as the return from a function. There are also special lists which are created just by running an application, or calling a subroutine. Perl lists are organic, able to grow as needed (unlike in C or Java, where you must explicitly state the expected size of your list, or use a special object to get this behavior).
my @namedList = (1,2,3,4); # an explicit list
# a deNovo list just when it is needed foreach my $thing (1,2,3,4) { print "$thing\n"; }
foreach my $ret (&somefunc()) { print $ret; }
- keys, values: hash functions which provide a list of the keys or values, respectively.
my %hash = ("key1" => "val1", "key2" => "val2" ); foreach my $key (keys %hash) { print "KEY $key is $hash{$key}\n"; }
foreach my $value (values %hash) { print "GOT VALUE $value\n"; }
- push: function which pushes a given scalar onto the end of an array.
my @array = (0..5); push @array, 7; #last element of @array now 7
- pop: permenantly removes and returns the last element of the given array (e.g. the array is shortened by 1). Returns undef if there are no more elements in the array.
my @array = (0..5); my $last = pop @array;# $last is 5, @array is now 0..4
#useful in while loops, because pop returns undef when finished while (my $cur = pop @array) { print "CURRENT IS $cur\n"; {
- shift: permenantly removes and returns the first element on the given array (e.g. the array is shortened by 1). Returns undef if there are no more elements in the array (useful in while loops, like pop).
my @array = (0..5); my $first = shift @array; #$first is 0, @array is now (1..5)
- unshift: places a given scalar onto the front of the given array.
my @array = (0..5); unshift @array, 7; # @array now 7,0,1,2,3,4,5
- @ARGV and @_: special arrays which are created at the beginning of a perl application (run on the commandline), or at the invocation of a subroutine (more later on these), respectively. Very rarely will you explicitly use @ARGV, though you will often use @_ explicitly. More often, you will use one of the above list functions (usually shift) on them implicitly, as they default to working on the one most relevant given the context of its usage (@ARGV anywhere within the (usually implied) main block, $_ anywhere within the block of a subroutine).
my ($arg1, $arg2) = @ARGV;
#better my $arg1 = shift; my $arg2 = shift;
#you can die with usage if an arg is undefined my $arg1 = shift or die "usage: myProg file1 [file2]\n"; my $arg2 = shift;
- slices: slices can be very useful in many situations. Basically, any array or hash (associative array), can be accessed as a smaller subset array/hash called a slice.
my $array _slice = @array[1,3,5];
my %hash_slice = @hash{"fred", "barney", "wilma"};
#remember l-values @array[3,5,7] = @other[2,4,6]; @garfield{"garfield","odie"} = @fuzzy{"bucky","satchel"}; my %sub_dictionary; @sub_dictionary{ &getSubKeys() } = @main_dictionary{&getSubKeys()};
- range_operator: this is a special shortcut operator which produces an ordered list of numbers from n to m.
foreach (0..15) { print unless($_ % 2); }
my @first_half = @array[0 .. ($#array/2)]; #although gets the larger half if odd length
- map: list function which processes a list into another list (e.g. it returns a list, using a block of code or expression provided. Blocks can be quite complex, spanning multiple lines, but they usually are not. Remember, map always runs the block of code on each element, and returns an orderd list of the results of these operations. If the evaluation of the block returns a nonsensical result for an element, or even undef, that return value still gets incorporated into the new list at the point of the element resulting in this result in the old list. Also, many people use map in a 'void return context', e.g. they use map instead of a foreach. This can be useful for debugging, but for production code it is much less memory efficient than foreach, because it produces the list in memory before throwning it away.
my @array = (0..10); my @newSimpleArray = map { ($_ / 2) * 10; } @array;
map { print } @newSimpleArray; #uses map in void return context.
- grep: like map, it iterates over a list to produce a new list. Unlike map, it always returns the actual element of the list (it doesnt return the processed value), but it only returns the element if the result of the block of code or expression returns true (perl true).
my @array = (0..10); my @evens = grep { ($_ % 2) ? undef : 1; } @array;
#what is wrong with the following code? my @badEvens = grep { ($_ % 2) ? undef : $_; } @array;
- sort: This function takes a list, and produces a new list of the elements sorted according to some logic. The default is to sort the elements in ascending order, but this behavior can be changed using a block of code, or subroutine (see below). There is no end to the ways that can be used to sort a list using your own, custom, sort routines. Sort routines have two special variables, $a and $b, which are fully functional scalars which magically appear (kind of like $_) during the evaluation of a block of code against the list provided. $a holds the current item in the list, $b holds the next item in the list. The sort function works according to a quicksort algorithm. Dont worry about the details, just know that sort works based upon the return of the sort block being one of:
  greater than zero: the current element goes after the next element   zero: the current element is equivalent to the next element   less than zero: the current element goes before the next element
To achieve this, you can write your own code to return this value manually based on some complex code, involving any data structures which are in scope within (above) the sort routine, or you can use the handy,dandy comparison operators <=> (numeric), and 'cmp' (string).
my @array = (3,2,5,1,0,4); my @ascending_default = sort @array; my @ascending_manual = sort { $a <=> $b } @array; my @ascending_really_manual = sort {   #return greater than zero if $a goes after $b   return 1 if ($a > $b);
  # return less than zero if $a goes before $b   return -1 if ($a < $b);
  #must be equivalent, return zero   return 0; } @array;
my @descending = sort { $b <=> $a } @array; my @descending_other_logic = sort { return $b - $a; } @ array; my @otherArray = qw(f e a d c b); my @sorted_with_function = sort myFunction @array;
sub myFunction { $otherArray[$a] cmp $otherArray[$b] }
#remember, $a and $b are fully functional scalars my @array_of_arrays_sorted_by_each_inner_arrays_first_element = sort { $a->[0] cmp $b->[0] } @array_of_arrays;
- Schwartzian Transforms: because map, grep, and sort all return lists, they can be chained into each other, the way that commands in UNIX can be piped into each other.
my @array = (240,301,2,1002,33);
my @complex_stuff = Â Â map { $_ / 2 } Â Â sort { $b <=> $a } Â Â grep { !($_ % 2) } @array;
List Processing, Slices, and @ARGV
|
|
Tip: To turn text into a link, highlight the text, then click on a page or file from the list above.
|
|
|
|
|
Comments (0)
You don't have permission to comment on this page.