Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw

two order sort

by ag4ve (Monk)
on Mar 05, 2013 at 00:09 UTC ( #1021725=perlquestion: print w/replies, xml ) Need Help??
ag4ve has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to sort a hashref of arrays first by the number of elements in the array and then the total count in all elements:
use List::Util qw(reduce); my $scan = {a => [ 5, 6 ], b => [ 5, 10, 15 ], c = [ 100 ], d => [ 8, +9 ] }; foreach my $sip (sort { $scan->{$b} <=> $scan->{$a} or +(reduce { $b + $a } @{$scan->{$b}}) <=> +(reduce +{$b + $a } @{$scan->{$a}}) } (keys %$scan))

Should print b, d, a, c but idk what it's currently doing.

Replies are listed 'Best First'.
Re: two order sort
by choroba (Chancellor) on Mar 05, 2013 at 00:17 UTC
    $scan->{$b} returns an array reference. You are comparing references which is not what you want. Change the first part of sort to
    $#{ $scan->{$b} } <=> $#{ $scan->{$a} }
    @{ $scan->{$b} } <=> @{ $scan->{$a} }
    لսႽ ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Re: two order sort
by AnomalousMonk (Chancellor) on Mar 05, 2013 at 01:05 UTC

    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
      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...


        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".

Re: two order sort
by LanX (Bishop) on Mar 05, 2013 at 00:32 UTC
    out of curiosity: why do you use reduce instead of sum from List::Util ?

    Cheers Rolf

Re: two order sort
by salva (Abbot) on Mar 05, 2013 at 11:39 UTC
    The problem may be related to both sort and reduce using the same global variables $a and $b.

    In any case, you can use Sort::Key:

    use Sort::Key::Multi 'ru_ru_keysort'; # sort by two unsigned keys in r +everse order use List::Util 'sum'; my @sorted = ru_ru_keysort { my $l = $scan->{$_}; (scalar(@$l), sum(@$l)) } keys %$scan;

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1021725]
Approved by Gangabass
[Tux]: so, another app with gtk GUI had something similar, but it defined the IM_MODULE(s) as cedilla.
[Tux]: when I set QT_IM_MODULE and GTK_IM_MODULE both to c<xim> and *unset* XMODIFIERS, all works fantastic
Tux => $HOME
[Tanktalus]: great, now I'm going to have to convert html codes to text for display... :)

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (12)
As of 2017-09-25 21:16 GMT
Find Nodes?
    Voting Booth?
    During the recent solar eclipse, I:

    Results (291 votes). Check out past polls.