Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
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 (Canon) 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: (5)
As of 2015-07-04 18:23 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (60 votes), past polls