Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

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

Comment on two order sort
Download Code
Re: two order sort
by choroba (Abbot) 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} }
    or
    @{ $scan->{$b} } <=> @{ $scan->{$a} }
    لսႽ ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Re: two order sort
by LanX (Canon) 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 AnomalousMonk (Abbot) 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...

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

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?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1021725]
Approved by Gangabass
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others musing on the Monastery: (11)
As of 2014-12-18 10:16 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (48 votes), past polls