First, you have a selection
problem, so you use a grep. Let's
not grep the values themselves but the index for
each item:
my @input_numbers = (1, 2, 4, 8, 16, 32, 64);
my @indices_of_odd_digit_sums = grep {
...
} 0..$#input_numbers;
Here, the expression 0..$#input_numbers will be a
list of indices for the array. Inside the block,
$_ is a small integer, from 0 to 6 (seven items
total). Now, you don't want to decide whether
$_ has an odd digit sum. You want to know whether
the array element at that index has an odd digit sum. Instead of
using $_ to get the number of interest, use
$input_numbers[$_]:
my @indices_of_odd_digit_sums = grep {
my $number = $input_numbers[$_];
my $sum;
$sum += $_ for split //, $number;
$sum % 2;
} 0..$#input_numbers;
The result will be the indices at which 1, 16, and 32 appear in the
list: 0, 4, and 5. You could use these indices in an array slice to
get the original values again:
my @odd_digit_sums = @input_numbers[ @indices_of_odd_digit_sums ];
The strategy here for an indirect grep or
map is to think of the $_
values as identifying a particular item of interest, such as the key
in a hash or the index of an array, and then use that identification
within the block or expression to access the actual values.
Here's another example: select the elements of
@x that are larger than the corresponding value in
@y. Again, you'll use the indices
of @x as your $_ items:
my @bigger_indices = grep {
if ($_ > $#y or $x[$_] > $y[$_]) {
1; # yes, select it
} else {
0; # no, don't select it
}
} 0..$#x;
my @bigger = @x[@bigger_indices];