Perl Array Sort -- How to Sort Arrays In Perl

Sorting arrays in the Perl programming language is actually very easy -- although the syntax you need to use can look a little strange at first.

Let's start with a simple program that sorts an array in alphabetical order.

use strict; 
use warnings; 

sub main
{
    # Declare and initialize an array.
    my @items = ("tree", "zebra", "apple", "fox");
    
    # Sort the array.
    @items = sort @items;
    
    # print the array contents.
    foreach my $item(@items) {
        print "$item\n";
    }
}

main();




apple
fox
tree
zebra




Note, the sorted array is returned from the sort() function; simply writing sort @items while ignoring the return value would not have caused the array to be sorted.

This simple program does not work with numbers. Watch what happens if we try to sort an array of numbers using the above technique.

use strict; 
use warnings; 

sub main
{
    # Declare and initialize an array.
    my @items = (0, 5, 10, 20);
    
    # Sort the array.
    @items = sort @items;
    
    # print the array contents.
    foreach my $item(@items) {
        print "$item\n";
    }
}

main();




0
10
20
5




The numbers are sorted alphabetically, not numerically. To handle anything other than the simplest form of alphabetical sort, we need to supply a sort algorithm as a code block to sort().

Sorting Arrays Using a Custom Sort Algorithm in Perl



In the following code it's a little confusing that the algorithm is a code block and not an argument (note, there's no comma after the sort algorithm), but that's Perl for you.

use strict; 
use warnings; 

sub main
{
    # Declare and initialize an array.
    my @items = (0, 5, 10, 20);
    
    # Sort the array.
    @items = sort {$a <=> $b} @items;
    
    # print the array contents.
    foreach my $item(@items) {
        print "$item\n";
    }
}

main();




0
5
10
20




Notice that the variables $a and $b are automatically supplied to the code block. These will be set to elements of the array that must be compared.

To implement the sort algorithm, use the following rules:


  • Return 1 if $a is greater than $b

  • Return -1 if $b is greater than $a

  • Return 0 if $a is equal to $b



In Perl, the return value of a function or code block is simply set to the last used value in the program if we don't supply an explicit return value.

The <=> operator performs the above comparisons for numbers.

(For strings, you must can use the cmp operator instead.)

So the above program could be written in a slightly-longer but more explicit and entirely equivalent fashion like this:

use strict; 
use warnings; 

sub main
{
    # Declare and initialize an array.
    my @items = (0, 5, 10, 20);
    
    # Sort the array.
    @items = sort {
        if($a > $b) {
            return 1;
        }
        elsif($b > $a) {
            return -1;
        }
        else {
            return 0;
        }
    } @items;
    
    # print the array contents.
    foreach my $item(@items) {
        print "$item\n";
    }
}

main();




If you want to sort in reverse order, you can simply switch $a and $b around.

Let's look at some examples of simple sorting, before moving on to more complex sorting.



Simple Array Sorting in Perl -- Some Examples



# Sort strings alphabetically
my @strings = ("fox", "cat", "apple");

my @sorted_strings = sort {$a cmp $b} @strings;

# Sort numbers numerically
my @numbers = (7, 10, 5.3, 8);

my @sorted_numbers = sort {$a <=> $b} @numbers;

# Sort numbers in descending numerical order.
my @reverse_sorted = sort {$b <=> $a} @numbers;





Complex Array Sorting in Perl



If you need to sort items according to some complex set of criteria in Perl, the same rules apply. However, for the sake of clarity you might want to use a whole separate function to supply your sorting algorithm rather than just using a code block.

The following program could be written a lot more simply, but you can use this as a template to implement your own custom sorting routines.

This program sorts a list of days given by name into the order they occur in the week.

use strict; 
use warnings; 

my %DAYS = (
    'Sun' => 0,
    'Mon' => 1,
    'Tue' => 2,
    'Wed' => 3,
    'Thu' => 4,
    'Fri' => 5,
    'Sat' => 6,
);

sub sort_days {
    # $a and $b will be automatically defined by sort().
    # Look up the position of the day in the week
    # using the DAYS hash.
    my $x = $DAYS{$a};
    my $y = $DAYS{$b};
    
    # Now we can just compare $x and $y. Note, it
    # would be simpler in this case to use the <=>
    # operator.
    if($x < $y) {
        return -1;
    }
    elsif($x > $y) {
        return 1;
    }
    else {
        return 0;
    }
}

sub main
{
    my @days = ("Tue", "Sat", "Wed", "Fri", "Mon");
    
    # Sort days in order using a sort algorithm
    # contained in a function.
    @days = sort sort_days @days;
    
    # Instead, here we could just do this:
    # @days = sort {$DAYS{$a} <=> $DAYS{$b}} @days;
    
    foreach my $day(@days) {
        print "$day\n";
    }
}



main();




Mon
Tue
Wed
Fri
Sat