Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

two order sort

by ag4ve (Monk)
on Mar 05, 2013 at 00:09 UTC ( [id://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.

Replies are listed 'Best First'.
Re: two order sort
by choroba (Cardinal) 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 AnomalousMonk (Archbishop) 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 LanX (Saint) 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 (Canon) 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
Domain Nodelet?
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?Last hourOther CB clients
Other Users?
Others sharing their wisdom with the Monastery: (6)
As of 2024-03-19 10:05 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found