in reply to sort by a multiple columns

print join "\n", map { join ',', @$_ } sort { for (0..($#{$a}<$#{$b}?$#{$b}:$#{$a})) { return $a->[$_] <=> $b->[$_] || $a->[$_] cmp $b->[$_] || next } } @un_sorted;
The mess on the for line determines how many elements there are in the longer of the two arrays being compared. The comparison is by number, then by string (so that null sorts before 0). If there's no difference either way, we continue through the loop. If there is a difference, it returns.

Update: I came up with a better way of handling different-length arrays below.


Caution: Contents may have been coded under pressure.

Replies are listed 'Best First'.
Re^2: sort by a multiple columns
by BrowserUk (Patriarch) on Sep 08, 2004 at 19:27 UTC

    You need to handle the case when comparing a shorter array with a longer one:

    #! perl -slw use strict; my @un_sorted = ([3,4,23,4,5],[3,4,56,2,4],[2,3,43,5,3],[2,3,43,6],[3, +4]); print join "\n", map{ join ',', @$_ } sort { for( 0 .. ( $#{$a} < $#{$b} ? $#{$b} : $#{$a} ) ) { return ( $a->[$_] || 0 ) <=> ( $b->[$_] || 0 ) || next } } @un_sorted; __END__ P:\test>before Use of uninitialized value in numeric comparison (<=>) at P:\test\junk +.pl line 10. 2,3,43,5,3 2,3,43,6 3,4 3,4,23,4,5 3,4,56,2,4 P:\test>after 2,3,43,5,3 2,3,43,6 3,4 3,4,23,4,5 3,4,56,2,4

    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail
    "Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon
      I'm sorry, but neither you nor Roy Johnson follow the OP insofar as he would like undefined array elements to be treated like infinity rather than zero, that is, he says he wants
      3,4,23,4,5 3,4,56,2,4 3,4
      instead of
      3,4 3,4,23,4,5 3,4,56,2,4
      Might just have been a typo though, as it's quite unusual.
      CombatSquirrel.

      Entropy is the tendency of everything going to hell.
        Good observation. The fix is surprisingly simple:
        sort { ## Compare through the shorter only for (0..(@$a>@$b ? $#{$b} : $#{$a})) { return $a->[$_] <=> $b->[$_] || next } ## If no difference, the longer array is first @$b <=> @$a;

        Caution: Contents may have been coded under pressure.

        Don't be sorry, your absolutely right :) Especially as my attempted correction of Roy Johnson's code was crap anyway.


        Examine what is said, not who speaks.
        "Efficiency is intelligent laziness." -David Dunham
        "Think for yourself!" - Abigail
        "Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon
      You're not really handling that case, you're just silencing a warning. Zero and undef still compare as equal. Note the use of cmp to differentiate zero from undef (I may have added that while you were typing your reply).

      Caution: Contents may have been coded under pressure.