http://www.perlmonks.org?node_id=1021729


in reply to two order sort

Multi-key sort, both in descending order:

>perl -wMstrict -le "use List::Util qw(sum); ;; my $scan = { a => [ 5, 6 ], b => [ 5, 10, 15 ], c => [ 100 ], d => [ 8, 9 ] }; ;; my @sorted = map $_->[0], sort { $b->[1] <=> $a->[1] or $b->[2] <=> $a->[2] } map [ $_, scalar @{ $scan->{$_} }, sum @{ $scan->{$_} } ], keys %$scan ; ;; print qq{@sorted}; " b d a c

Replies are listed 'Best First'.
Re^2: two order sort
by LanX (Saint) on Mar 05, 2013 at 01:30 UTC
    you forgot to tell that your (Schwarzian) approach is not only better readable but much faster, because the sums are only calculated once per entry. =)

    Cheers Rolf

      A decorate-sort-undecorate or GRT (Guttman-Rosler Transform) approach would be even faster, but I forgot how to decorate for descending sort. It's probably somewhere in A Fresh Look at Efficient Perl Sorting. Must look it up...

      Updates:

      1. See also Sort::Maker.
      2. According to the Wikipedia article linked by LanX herein, "decorate-sort-undecorate" is just another term for "Schwartzian Transform".

        I forgot how to decorate for descending sort.

        Just negate the field(s). Unary minus ('-') for numeric and boolean not ('~') for alpha:

        # Ascending numeric and ascending alpha print for map{ unpack 'x[Na4]a*', $_ } sort map{ local $^W; pack 'Na4a*', (0+$_), substr( $_, 1), $_ } @a;; 0cjlf 0dvys 0uvmu 1akkn 1imwi 1lpys 1pjzw 2uwep 3hiyn 3jrkx 3myrn 3ozcw 3rqhx 3vkon 6excm 7axqf 7lbhj 8klfd 9ijei 9klou # Descending numeric and ascending alpha print for map{ unpack 'x[Na4]a*', $_ } sort map{ local $^W; pack 'Na4a*', -(0+$_), substr( $_, 1), $_ } @a;; 0cjlf 0dvys 0uvmu 9ijei 9klou 8klfd 7axqf 7lbhj 6excm 3hiyn 3jrkx 3myrn 3ozcw 3rqhx 3vkon 2uwep 1akkn 1imwi 1lpys 1pjzw # Ascending numeric and descending alpha print for map{ unpack 'x[Na4]a*', $_ } sort map{ local $^W; pack 'Na4a*', (0+$_), ~substr( $_, 1), $_ } @a;; 0uvmu 0dvys 0cjlf 1pjzw 1lpys 1imwi 1akkn 2uwep 3vkon 3rqhx 3ozcw 3myrn 3jrkx 3hiyn 6excm 7lbhj 7axqf 8klfd 9klou 9ijei # Decending numeric and descending alpha print for map{ unpack 'x[Na4]a*', $_ } sort map{ local $^W; pack 'Na4a*', -(0+$_), ~substr( $_, 1), $_ } @a;; 0uvmu 0dvys 0cjlf 9klou 9ijei 8klfd 7lbhj 7axqf 6excm 3vkon 3rqhx 3ozcw 3myrn 3jrkx 3hiyn 2uwep 1pjzw 1lpys 1imwi 1akkn

        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
        > > your (Schwarzian) approach is not only better readable ...

        > A decorate-sort-undecorate or GRT approach would be even faster,

        I'm confused, IMHO "Schwartzian Transform" and "Decorate-Sort-Undecorate" are two names of the same thing ... right ???

        EDIT: see also Decorate-Sort-Undecorate in WP.

        UPDATE: OK I got it. You were referring to GRT beeing faster. =)

        (Advanced Sorting - GRT - Guttman Rosler Transform)

        Well in this case creating a float separating the two numeric values by a point should be fast enough.

        Cheers Rolf

        Thanks for the routine and the module (and the article - I'll have to read that). The code works great.