tags:

views:

68

answers:

3

Let's say I have this list:

my @list = qw(one two three four five);

and I want to grab all the elements containing o. I'd have this:

my @containing_o = grep { /o/ } @list;

But what would I have to do to also receive an index, or to be able to access the index in grep's body?

+8  A: 

 

my @index_containing_o = grep { $list[$_] =~ /o/ } 0..$#list;  # ==> (0,1,3)

my %hash_of_containing_o = map { $list[$_]=~/o/?($list[$_]=>$_):() } 0..$#list
            # ==> ( 'one' => 0, 'two' => 1, 'four' => 3 )
mobrule
Nice thinking :) !
Geo
+8  A: 

Take a look at List::MoreUtils. You can do lots of handy things with arrays without having to roll your own version, plus it's faster (because it's implemented in C/XS):

use List::MoreUtils qw(first_index indexes);

my $index_of_matching_element = first_index { /o/ } @list;

For all matching indices, and then their corresponding elements, you can do:

my @matching_indices = indexes { /o/ } @list;
my @matching_values = @list[@matching_indices];

or just:

my @matching_values = grep { /o/ } @list;
Ether
Won't this return just the index of the first element?
Geo
Yep. I think Ether meant to use the `indexes` function which will give a list of all indexes that return true for the block.
friedo
Yes I did... I hit submit too soon before checking my work. thanks :)
Ether
+1 for mentioning the fact that it's C/XS implementation makes it faster
Zaid
+1  A: 

This populates 2 arrays with what you want, looping through the input array once:

use strict;
use warnings;
my @list = qw(one two three four five);
my @containing_o;
my @indexes_o;
for (0 .. $#list) {
    if ($list[$_] =~ /o/) {
        push @containing_o, $list[$_];
        push @indexes_o   , $_;
    }
}
toolic