Search code examples
arraysperlsortingnumerical

Perl: Numerical sort of arrays in a hash 2 (Schwarzian Transform)


This is actually a follow-up of this thread: Perl: Numerical sort of arrays in a hash

I couldn't edit the original question because my current code is a bit different, so I'm just asking this as another question.

Okay after using the Schwarzian Transform, I have this:

my @mylines =("0.899 0.92 cat", 
            "9.999 0.001 dog",
            "-0.52 0.3 humpty", 
            "13.52 0.09 bumbo",
            "-1.52 0.98 nanny",
            "3.52 0.34 lala");

my @sorted = map { join ' ', @$_ }
             reverse sort { $a->[0] cmp $b->[0] or $a->[1] <=> $b->[1] }
             map { [ split ] } (@mylines);

print "$_\n" for @sorted;

I would expect the output to be sorted first by the first column, then the second, but it turns out like this:

9.999 0.001 dog
3.52 0.34 lala
13.52 0.09 bumbo
0.899 0.92 cat
-1.52 0.98 nanny
-0.52 0.3 humpty

I suppose that's because it's doing a character sort... but I need it numerically sorted. Do I need to put a java-like "parseInt()" somewhere in the sort function?


Solution

  • You are doing a cmp on the first column. That means it sorts it as text. Your sort function should be:

    sort { $a->[0] <=> $b->[0] or $a->[1] <=> $b->[1] } ...
    

    Which makes the output:

    13.52 0.09 bumbo
    9.999 0.001 dog
    3.52 0.34 lala
    0.899 0.92 cat
    -0.52 0.3 humpty
    -1.52 0.98 nanny
    

    However, you should never need to put a reverse before sort, because you can always reverse the terms:

    sort { $b->[0] <=> $a->[0] or $b->[1] <=> $a->[1] } ...