data-structures intermediate

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 the grep block
  • $_ % 2 == 0 checks if the number is divisible by 2 (even)
  • grep returns the list of elements where the block evaluates to true

Context and Sigils

  • grep is 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 grep returns a list; if you assign to a scalar, it returns the count of matching elements.
  • $_ is aliased to the elements so modifying $_ inside grep will modify the original list elements.
  • grep evaluates in list context, so it’s not suited for filtering large data streams element-by-element (use map or other methods if side effects needed).
  • The idiom grep { !condition } list is 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 grep with 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

Tip: edit code and use “Run (Browser)”. Server runs always execute the published, verified snippet.
STDOUT
(empty)
STDERR
(empty)

Was this helpful?

Related Questions