Perl Hash / array slices

Hash / array slices allow you to access or manipulate multiple elements of a hash or array at the same time.

Hash and array slices both use @ to denote the slice, hash slices use curly braces ({}) whereas array slices use square brackets ([]).

At first glance hash/array slices can look quite mysterious, but they're very powerful for certain situations.

Hash slices

A simple hash slice looks like:

my @values = @hash{$key1, $key2, $key3, $key4};

A more in-depth example, and showing assignment to a hash slice:

my %stock = (
    apples  => 10,
    bananas => 13,
    oranges => 25,
    pears   => 17
);
 
# quick stock check:
my ($apples, $oranges) = @stock{ qw(apples oranges) };
 
# we made a sale: (assignment to hash slice:)
@stock{ qw/apples oranges/ } = (8, 21);

Further example of assignment of a slice of one hash to another, and showing the use of a hashref in a slice:

my $hashref = { foo => 'foo1', bar => 'bar1' };
 
my %hash2;
 
@hash2{ qw(foo bar) } = @$hashref{ qw(foo bar) };

Notice the use of @$hash to deference the hashref on the go. You could dereference it first, which may be slightly clearer, but probably unnecessary in this case, with:

my %realhash = %{$hashref};

Array slices

Getting values using an array slice:

# sets $foo and $bar to the 2nd and 3rd elements of @array:
my ($foo, $bar) = @array[ 1 , 2 ];
 
# assigns last four values from array to variables
my ($a, $b, $c, $d) = @big_array[ -1 .. -4 ];

Assigning to an array slice:

# change values of 20th to 50th elements of @big_array
@big_array[ 20 .. 50 ] = ( 10 .. 20 );

Slices can be used on the results of functions which return lists, ideal when you only want a couple of items from the list which is returned, and don't want to have to store the returned list first: # use slices on the results of functions which return lists:

my ($day, $month, $year) = (localtime())[3, 4, 5];

Hash slices as lookup tables

A common use of hash slices is to create a look-up table for data stored in an array. As hash look-ups occur in constant time while random searches across an array occur in polynomial time, using hash slices increases the efficiency of your code.

# The array of things we'd like to test against
my @colours = qw/red green yellow orange white mauve blue ochre
		pink purple gold silver grey brown steel/;
 
# A list of things that might be in @colours or not
my @find = qw/red blue green black/;
 
# hashes and arrays can have the same names.
# hash slices use curly braces {}
# array slices use square brackets []
my %colours;
 
# set all values in %colours from the keys in @colours to
# have the undefined value (but exist in the hash).
@colours{@colours} = ();
 
# We now look for @find in %colours rather than @colours.
foreach my $colour (@find) {
    if(exists($colours{$colour} )) {
 
        print "$colour exists\n";
 
    } else {
 
        print "$colour is unknown\n";
 
    }
}

References:

  • http:mailman.anu.edu.au/pipermail/perl.sig/2005-September/000014.html ~~DISCUSSION~~
 
perl/hashslice.txt · Last modified: 2010/02/26 10:45 (external edit)
 
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki