If I have an array myarray
in Python, I can use the slice notation
myarray[0::2]
to select only the even-indexed elements. For
I've written the module List::Gen on CPAN that provides an alternative way to do this:
use List::Gen qw/by/;
my @array = qw/zero one two three four five six/;
my @slice = map {$$_[0]} by 2 => @array;
by
partitions @array
into groups of two elements and returns an array of array references. map
then gets this list, so each $_
in the map will be an array reference. $$_[0]
(which could also be written $_->[0]
) then grabs the first element of each group that by
created.
Or, using the mapn
function which by
uses internally:
use List::Gen qw/mapn/;
my @slice = mapn {$_[0]} 2 => @array;
Or, if your source list is huge and you may only need certain elements, you can use List::Gen
's lazy lists:
use List::Gen qw/by gen/;
my $slicer = gen {$$_[0]} by 2 => @array;
$slicer
is now a lazy list (an array ref) that will generate it's slices on demand without processing anything that you didn't ask for. $slicer
also has a bunch of accessor methods if you don't want to use it as an array ref.
If you don't care about the order, and if the odd-numbered elements of the list are unique, you can concisely convert the array to a hash and take the values
:
@even_elements = values %{{@array}};
@odd_elements = keys %{{@array}};
(No, this is not a serious answer)
Another way would be by using grep
:
my @array = qw( zero one two three four five six );
print map { "$_ " } @array[grep { !($_ & 1) } 0 .. $#array]; #even
Output:zero two four six
print map { "$_ " } @array[grep { ($_ & 1) } 0 .. $#array]; #odd
Output:one three five
There's array slices:
my @slice = @array[1,42,23,0];
There's a way to to generate lists between $x and $y:
my @list = $x .. $y
There's a way to build new lists from lists:
my @new = map { $_ * 2 } @list;
And there's a way to get the length of an array:
my $len = $#array;
Put together:
my @even_indexed_elements = @array[map { $_ * 2 } 0 .. int($#array / 2)];
Granted, not quite as nice as the python equivalent, but it does the same job, and you can of course put that in a subroutine if you're using it a lot and want to save yourself from some writing.
Also there's quite possibly something that'd allow writing this in a more natural way in List::AllUtils
.