Home » Tutorials » Sort function |
The sort function sorts a list (an array). The default is to sort alphabetically. However, you can define your own sorts to get around numbers and complex data structures.
#!/usr/bin/perl use strict; use warnings; my @strings = ("Becky", "Simon", "Bianca", "Steven", "Greg", "Andrew"); my @sorted_strings = sort @strings; print "@sorted_strings\n";
This gives you the following output:
Andrew Becky Bianca Greg Simon Steven
The Perl sort function sorts by strings instead of by numbers. If you were to use:
#!/usr/bin/perl use strict; use warnings; my @numbers = (23, 1, 22, 7, 109, 9, 65, 3); my @sorted_numbers = sort @numbers; print "@sorted_numbers\n";
The output you would see would be:
1 109 22 23 3 65 7 9
To sort numerically, declare your own sort block and use the flying saucer operator <=>:
#!/usr/bin/perl use strict; use warnings; my @numbers = (23, 1, 22, 7, 109, 9, 65, 3); my @sorted_numbers = sort {$a <=> $b} @numbers; print "@sorted_numbers\n";
The output would now be:
1 3 7 9 22 23 65 109
Note that $a and $b do not need to be declared, even with use strict on, because they are special sorting variables.
To sort backwards you need to declare your own sort block, and simply put $b before $a.
For example, the standard sort is as follows:
#!/usr/bin/perl use strict; use warnings; my @strings = ("Becky", "Simon", "Bianca", "Steven", "Greg", "Andrew"); my @sorted_strings = sort @strings; print "@sorted_strings\n";
The output would be:
Andrew Becky Bianca Greg Simon Steven
To do the same, but in reverse order:
#!/usr/bin/perl use strict; use warnings; my @strings = ("Becky", "Simon", "Bianca", "Steven", "Greg", "Andrew"); my @sorted_strings = sort {$b cmp $a} @strings; print "@sorted_strings\n";
The output is:
Steven Simon Greg Bianca Becky Andrew
And for numbers:
#!/usr/bin/perl use strict; use warnings; my @numbers = (23, 1, 22, 7, 109, 9, 65, 3); my @sorted_numbers = sort {$b <=> $a} @numbers; print "@sorted_numbers\n";
The output is:
109 65 23 22 9 7 3 1
Of course, in both these cases there is another way:
#!/usr/bin/perl use strict; use warnings; my @strings = ("Becky", "Simon", "Bianca", "Steven", "Greg", "Andrew"); my @sorted_strings = reverse sort @strings; print "@sorted_strings\n";
The output is:
Steven Simon Greg Bianca Becky Andrew
And
#!/usr/bin/perl use strict; use warnings; my @numbers = (23, 1, 22, 7, 109, 9, 65, 3); my @sorted_numbers = reverse sort {$a <=> $b} @numbers; print "@sorted_numbers\n";
The output is:
109 65 23 22 9 7 3 1
You can use sort to order hashes. For example, if you had a hash as follows:
#!/usr/bin/perl use strict; use warnings; my %data = ( bananas => 1, oranges => 7, apples => 12, mangoes => 3, pears => 8, );
And you wanted to display the fruit sorted alphabetically, you could do this:
#!/usr/bin/perl use strict; use warnings; my %data = ( bananas => 1, oranges => 7, apples => 12, mangoes => 3, pears => 8, ); foreach my $fruit (sort keys %data) { print $fruit . ": " . $data{$fruit} . "\n"; }
Output:
apples: 12 bananas: 1 mangoes: 3 oranges: 7 pears: 8
If you wanted to sort the same hash by the values (i.e. the number beside each fruit), you could do the following:
#!/usr/bin/perl use strict; use warnings; my %data = ( bananas => 1, oranges => 7, apples => 12, mangoes => 3, pears => 8, ); # Using <=> instead of cmp because of the numbers foreach my $fruit (sort {$data{$a} <=> $data{$b}} keys %data) { print $fruit . ": " . $data{$fruit} . "\n"; }
Output:
bananas: 1 mangoes: 3 oranges: 7 pears: 8 apples: 12
You can also use sort to sort more complex data structures. For example, if you had an array of hashes:
my @people = ( { name => 'Becky', age => 23}, { name => 'Simon', age => 43}, { name => 'Bianca', age => 29}, { name => 'Steven', age => 23}, { name => 'Greg', age => 50}, { name => 'Andrew', age => 19}, );
And you wish to display the data about the uses, in alphabetical order, you could do the following:
#!/usr/bin/perl use strict; use warnings; my @people = ( { name => 'Becky', age => 23}, { name => 'Simon', age => 43}, { name => 'Bianca', age => 29}, { name => 'Steven', age => 23}, { name => 'Greg', age => 50}, { name => 'Andrew', age => 19}, ); foreach my $person (sort {$a->{name} cmp $b->{name}} @people) { print $person->{name} . " is " . $person->{age} . "\n"; }
The output is:
Andrew is 19 Becky is 23 Bianca is 29 Greg is 50 Simon is 43 Steven is 23
Rather than writing the code inline, you can also pass in a subroutine name. The subroutine needs to return an integer less than, equal to, or greater than 0. Do not modify the $a and $b variables as they are passed in by reference, and modifying them will probably confuse your sorting.
#!/usr/bin/perl use strict; use warnings; my @people = ( { name => 'Becky', age => 23}, { name => 'Simon', age => 43}, { name => 'Bianca', age => 29}, { name => 'Steven', age => 23}, { name => 'Greg', age => 50}, { name => 'Andrew', age => 19}, ); foreach my $person (sort byage @people) { print $person->{name} . " is " . $person->{age} . "\n"; } sub byage { $a->{age} <=> $b->{age}; }
The output would be:
Andrew is 19 Becky is 23 Steven is 23 Bianca is 29 Simon is 43 Greg is 50
To find out more, run the command:
perldoc -f sort