How to sort numbers in Perl?

print "@_\n";
4109 4121 6823 12967 12971 14003 20186

How do I sort it in Perl?

Using @sorted = sort(@_); gives me an alphabetical ordering

13041 13045 14003 20186 4109 4121 6823

How do I get a numerical ordering? Does Perl have built-in functions for merge-sort, insertion-sort etc.?

Answers


You can pass a custom comparison function to Perl's sort routine. Just use:

@sorted = sort { $a <=> $b } @unsorted;

The sort function accepts a custom comparison function as its first argument, in the form of a code block. The {...} part is just this code block (see http://perldoc.perl.org/functions/sort.html ).

sort will call this custom comparison function whenever it needs to compare two elements from the array to be sorted. sort always passes in the two values to compare as $a, $b, and the comparison function has to return the result of the comparison. In this case it just uses the operator for numeric comparison (see http://perldoc.perl.org/perlop.html#Equality-Operators ), which was probably created just for this purpose :-).

Solution shamelessly stolen from "Perl Cookbook", Chapter 04 Sub-chapter 15 (buy the book - it's worth it!)


Supply a comparison function to sort():

# sort numerically ascending
my @articles = sort {$a <=> $b} @files;

# sort numerically descending
my @articles = sort {$b <=> $a} @files;

The default sort function is cmp, string comparison, which would sort (1, 2, 10) into (1, 10, 2) . <=> , used above, is the numerical comparison operator.


Perl's sort by default sorts alphabetically in ASCII order. To sort numerically you can use:

@sorted = sort { $a <=> $b } @_;

This is a Perl FAQ. From the command line:

perldoc -q sort

perlfaq4: How do I sort an array by (anything)?


@l = (4109, 4121, 6823, 12967, 12971, 14003, 20186, 1, 3, 4);
@l = sort { $a <=> $b } @l;
print "@l\n"; # 1 3 4 4109 4121 6823 12967 12971 14003 20186

You have to supply your own sorting subroutine { $a <=> $b }


You can predefine function which should be used to comparing values in your array. perldoc -f sort gives you an example:

# sort using explicit subroutine name
sub byage {
   $age{$a} <=> $age{$b};  # presuming numeric
}
@sortedclass = sort byage @class;

<=> operator is used to sort numerically.

@sorted = sort {$a <=> $b} @unsorted;

I just want to save a lot of time for anyone, new in Perl (like me) who has this question, i.e. how to sort a numeric array, because I have not only lost time but is has driven me crazy!

So, you find here (and in a lot of other places) that the way to sort a numeric array is:

@sorted_array = sort { $a <=> $b } @unsorted_array;

Now you try it, and you get an error: "Can't use "my $a" in sort comparison" ! (This is because you have already declared '$a', using 'strict.pm'). But then, you can't use non declared variables either since they will be rejected as undefined! So, you might feel trapped in an impasse, as I did.

I had to solve this problem "the hard way", just because no one has cared -- either in here, or in perldoc.perl.org, or in any other place I visited -- to mention that '$a' AND '$b' ARE RESERVED (TOKENS) FOR THIS USE! (This of course when one uses 'strict', which one should. And which is quite crazy, because 'a' and 'b' are amongst the most common short variables used in programming, and logically so!)

I hope that this will be of help to a lot of programmers, new in Perl, who will visit this page!


Need Your Help

Download maps for osmdroid

android osmdroid

I am developing an application in which I need to use maps offline. I'm using osmdroid and osmbonuspack

ng-class condition changes, but not updating classes

javascript angularjs ng-class

I have a very strange issue. I have to set an active class on the appropriate &lt;li&gt; when the $scope.selectedCat == cat.id. The list is generated with ng-repeat. If selectedCat is false, the 'B...