rvosa has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks,

I have a question about the Schwartzian transform on multidimensional arrays (at least, I think that's what I need). Here's a typical array:
@AoA = ( [ "n1", "34" ], [ "n3", "14" ], [ "n2", "1" ], [ "n4", "5" ], );
I want these sorted numerically on the second dimension, the numerical values. What I'm looking for is:
@sorted = ( [ "n2", "1" ], [ "n4", "5" ], [ "n3", "14" ], [ "n1", "34" ], );
Naively, I figured something like the following would work:
@sorted = map { [ $_[0], $_[1] ] } sort { $a->[1] <=> $b->[1] } map { +[ $_[0], $_[1] ] } @AoA;
But I seem to get nothing but emptiness... so how is this done the right way?

Thanks, any replies greatly appreciated.

Replies are listed 'Best First'.
Re: Do the Schwartzian boogy!
by PodMaster (Abbot) on May 30, 2005 at 09:53 UTC
    @AoA is already in schwartzian form
    @AoA = ( [ "n1", "34" ], [ "n3", "14" ], [ "n2", "1" ], [ "n4", "5" ], ); @sorted = sort { $a->[1] <=> $b->[1] } @AoA; use Data::Dumper; $Data::Dumper::Indent=1;die Dumper\@sorted; __END__ $VAR1 = [ [ 'n2', 1 ], [ 'n4', 5 ], [ 'n3', 14 ], [ 'n1', 34 ] ];

    MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
    I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
    ** The third rule of perl club is a statement of fact: pod is sexy.

      Oops... d'oh... of course... that works. Thank you! Problem solved. I was thinking far too complicated...
Re: Do the Schwartzian boogy!
by salva (Canon) on May 30, 2005 at 10:10 UTC
    you can forget about the ST!
    use Sort::Key qw(nkeysort); my @sorted = nkeysort { $_->[1] } @AoA;
    Sort::Key is much faster than the ST or even than the GRT and also easier to use... though still beta.
      Well done, Salva! How does it work? XS is quite beyond my abilities right now...
        it is more or less equivalent to:
        sub keysort (&@) { my ($keygen, @values) = @_; my @keys = map { &$keygen() } @values; my @ix = sort { $keys[$a] cmp $keys[$b] } 0..$#keys; @values[@ix]; }
        but implemented in C so there is no performance penalty because of the sort whith a custom comparison body (the heavy part of the alghorithm, with O(NlogN) cost).

        It also uses native C types to represent the keys when those are numbers, and tries to move or copy data around as less as possible.

Re: Do the Schwartzian boogy!
by polettix (Vicar) on May 30, 2005 at 10:02 UTC
    You don't need it! The ST works on the principle that you add the sort field, sort according to it, then remove it.

    Your case is much simpler (assuming you want to create copies):

    #!/usr/bin/perl use strict; use warnings; use Data::Dumper; my @AoA = ( [ "n1", "34" ], [ "n3", "14" ], [ "n2", "1" ], [ "n4", "5" ], ); my @sorted = map { [ @$_ ] } sort { $a->[1] <=> $b->[1] } @AoA; print Dumper(\@sorted); __END__ $VAR1 = [ [ 'n2', 1 ], [ 'n4', 5 ], [ 'n3', 14 ], [ 'n1', 34 ] ];
    Note that the map gets array references as $_, not pairs in @_.

    Flavio (perl -e 'print(scalar(reverse("\nti.xittelop\@oivalf")))')

    Don't fool yourself.