SoFunction
Updated on 2025-04-07

Perl array sorting learning notes

In this article, we learn how to use Perl to sort strings or arrays of numbers.

Perl has a built-in function called sort that can undoubtedly sort an array. Its simplest form is to pass an array, which returns an array composed of sorted elements. @sorted = sort @original.

Based on ASCII code sorting

Copy the codeThe code is as follows:

#!/usr/bin/perl
use strict;
use warnings;
use 5.010;
 
use Data::Dumper qw(Dumper);
 
my @words = qw(foo bar zorg moo);
 
say Dumper \@words;
 
my @sorted_words = sort @words;
 
say Dumper \@sorted_words;

The above example will be printed
Copy the codeThe code is as follows:

$VAR1 = [
        'foo',
        'bar',
        'zorg',
        'moo'
      ];
 
$VAR1 = [
        'bar',
        'foo',
        'moo',
        'zorg'
      ];

The first output shows the array before sorting, and the second is after sorting.

This is the easiest case, but it may not be what you want. For example, what if some words start with capital letters?

Copy the codeThe code is as follows:

my @words = qw(foo bar Zorg moo);
The result in @sorted_names will be:

$VAR1 = [
        'Zorg',
        'bar',
        'foo',
        'moo'
      ];


You will find that words starting with capital letters come first. This is because sort is sorted by ASCII code table by default, and all uppercase letters are ranked before lowercase letters.

Comparison function

Perl's sort works like this, it traverses every two elements of the original array; each time put the left value into the variable $a and the right value into the variable $b. Then call the comparison function. If the content of $a should be on the left, the "compare function" will return 1; if $b should be on the left, it will return -1, and if both are the same, it will return 0.

Usually you don't see the comparison function, sort will compare the values ​​based on the ASCII code table, but if you want, you can write it explicitly:

Copy the codeThe code is as follows:

sort { $a cmp $b } @words;

This code will achieve the same effect as sort @words without blocks.

Here you can see that by default perl uses cmp as the comparison function. This is because cmp can do the work we need here. It compares the values ​​of strings on both sides. If the left parameter is "less than" the right parameter, it returns 1; if the left parameter is "greater than" the right parameter, it returns -1; if it is equal, it returns 0.

Alphabetical order
If you want to ignore the case of strings to sort - commonly known as alphabetical order, you can do it like the next example:

Copy the codeThe code is as follows:

my @sorted_words = sort { lc($a) cmp lc($b) } @words;

For comparison here, we call the lc function to return the lowercase version of the parameter. Then cmp compares these lowercase versions and decides who comes first and who comes after the original string.

turn out

Copy the codeThe code is as follows:

$VAR1 = [
        'bar',
        'foo',
        'moo',
        'Zorg'
      ];

Perl logarithmic sorting
If you use sort on the numeric array to perform default sorting, the result may not be what we expect.

Copy the codeThe code is as follows:

my @numbers = (14, 3, 12, 2, 23);
my @sorted_numbers = sort @numbers;
say Dumper \@sorted_numbers;
$VAR1 = [
        12,
        14,
        2,
        23,
        3
      ];

If you think about it carefully, it is not surprising. When the comparison function sees 12 and 3, it compares by string. This means comparing the first characters "1" and "3" of two strings. In the ASCII code table, "1" is before "3", so the string "12" will be before the string "3".

Perl won't magically guess that you want to sort these values ​​by numbers.

Although we can write a comparison function to compare two values ​​by number. But here we use <=> (also known as the spaceship operator), which compares two parameters by numbers and returns 1, -1, or 0.

Copy the codeThe code is as follows:

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

turn out:

Copy the codeThe code is as follows:

$VAR1 = [
        2,
        3,
        12,
        14,
        23
      ];