Sorting By Functions in Perl

Sometimes we’ll want to sort a collection by something other than its natural order. For example, suppose we wanted to sort strings by their length instead of alphabetically. Here’s an example of custom sorts in Perl.

use strict;
use warnings;
use List::Util qw(sort_by);

my @fruits = ("peach", "banana", "kiwi");

# We implement a comparison function for string lengths.
my $len_cmp = sub {
    my ($a, $b) = @_;
    return length($a) <=> length($b);
};

# Now we can use sort_by with this custom comparison function to sort @fruits by name length.
@fruits = sort_by { $len_cmp->($a, $b) } @fruits;
print join(", ", @fruits) . "\n";

# We can use the same technique to sort an array of values that aren't built-in types.
package Person;
sub new {
    my ($class, $name, $age) = @_;
    return bless { name => $name, age => $age }, $class;
}

my @people = (
    Person->new("Jax", 37),
    Person->new("TJ", 25),
    Person->new("Alex", 72)
);

# Sort @people by age using sort_by.
@people = sort_by { $_->{age} } @people;
print join(", ", map { "$_->{name}($_->{age})" } @people) . "\n";

In this Perl example, we’re using the List::Util module which provides sort_by, a function that allows us to sort based on a custom criterion.

For sorting strings by length, we define a comparison function $len_cmp that compares the lengths of two strings. We then use this with sort_by to sort the @fruits array.

For sorting custom objects, we define a simple Person class. We then create an array of Person objects and sort them by age using sort_by.

Note that Perl’s sorting is typically more concise than many other languages, as it allows direct comparison in the sorting function. If you need more complex comparisons, you can always define a separate comparison function as we did with $len_cmp.

When you run this script, you should see output similar to:

kiwi, peach, banana
TJ(25), Jax(37), Alex(72)

This demonstrates how we can use custom sorting in Perl for both simple types and custom objects.