How to use grep to filter array elements in Perl?
Question
How to use grep to filter array elements in Perl?
In Perl, the grep function is a powerful and concise way to filter elements from a list or array based on a condition you specify. It evaluates each element against a block or expression and returns a list of elements for which the condition is true. This makes grep ideal for filtering arrays without the need for explicit loops.
How grep works in Perl
The syntax for grep is:
grep BLOCK LIST
or
grep EXPR, LIST
The BLOCK is a snippet of code where the current element is accessed via the $_ variable. For each element of LIST, Perl evaluates the block; if the block returns a true value, that element is included in the result.
Example: Filtering numeric arrays
Suppose you want to filter only even numbers from an array of integers. Using grep, that looks like this:
#!/usr/bin/perl
use strict;
use warnings;
my @numbers = (1, 2, 3, 4, 5, 6);
my @evens = grep { $_ % 2 == 0 } @numbers;
print "Even numbers: @evens\n";
This will output:
Even numbers: 2 4 6
Explanation:
$_is the default variable holding the current element in thegrepblock$_ % 2 == 0checks if the number is divisible by 2 (even)grepreturns the list of elements where the block evaluates to true
Context and Sigils
grepis list context by default, returning a filtered list- You can assign the result to an array (
@filtered) or scalar ($count = grep ...), but in scalar context it returns the number of matches $_is the default place where each list element is aliased temporarily within the block
Filtering strings and pattern matching
grep is commonly used with regular expressions to filter strings. For example, to filter words containing the letter "a":
my @words = qw(apple banana cherry date elderberry);
my @with_a = grep { /a/ } @words; # elements matching /a/
print "Words with 'a': @with_a\n";
Common gotchas and tips
- Remember
grepreturns a list; if you assign to a scalar, it returns the count of matching elements. $_is aliased to the elements so modifying$_insidegrepwill modify the original list elements.grepevaluates in list context, so it’s not suited for filtering large data streams element-by-element (usemapor other methods if side effects needed).- The idiom
grep { !condition } listis used to filter out elements NOT matching the condition.
Complete runnable example
#!/usr/bin/perl
use strict;
use warnings;
my @data = (10, 15, 20, 25, 30, 35);
# Filter elements greater than 20
my @gt_20 = grep { $_ > 20 } @data;
print "Elements greater than 20: @gt_20\n";
# Filter elements NOT divisible by 10
my @not_div_10 = grep { $_ % 10 != 0 } @data;
print "Elements not divisible by 10: @not_div_10\n";
# Count how many elements are divisible by 5
my $count_div_5 = grep { $_ % 5 == 0 } @data;
print "Count of elements divisible by 5: $count_div_5\n";
This script prints:
Elements greater than 20: 25 30 35
Elements not divisible by 10: 15 25 35
Count of elements divisible by 5: 6
Summary
grep is an idiomatic, concise way to filter arrays in Perl using any arbitrary condition. It leverages the magic of $_ and list context to provide highly readable and flexible filtering.
- Use
grepwith a block to filter based on complex conditions - Remember scalar vs list context differences
- Be mindful of aliased
$_for side effects - Utilize pattern matching for string filtering
Mastering grep will greatly simplify your Perl data filtering tasks while embracing the language’s "There’s More Than One Way To Do It" (TMTOWTDI) philosophy.
Verified Code
Executed in a sandbox to capture real output. • v5.34.1 • 6ms
(empty)(empty)