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

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hello Monks!
I have a hash, which I have sorted based on its values, so, apparently, the %keys array of the sorted hash are the values of the initial array.
What I would like to do is to reduce this %keys array recursively, by, let's say 10 elements each time, so, the first time I would get the first 10 elements, the second time, the next 10 etc...
Is there any easy way to do this?
Thanks

Replies are listed 'Best First'.
Re: recursively reduce an array
by Limbic~Region (Chancellor) on Nov 05, 2012 at 22:09 UTC
    Anonymous Monk,
    Hashes aren't sorted - even with Tie::Hash::Sorted which appears to be sorted, there are things going on under the covers to make it look like it is sorted.

    It sounds like what you have is this:

    my @sorted_keys = sort keys %hash; while (@sorted_keys) { my @ten = splice(@sorted_keys, 0, 10); # Do something with @ten }
    If that isn't what you mean, you will need to try and provide more context or hope one of the other monks has guessed better than myself.

    Cheers - L~R

Re: recursively reduce an array
by rjt (Curate) on Nov 05, 2012 at 22:56 UTC

    You say you want to recursively sort an array, so I'll assume you've already done something like:

    my @sorted = sort keys %hash;

    From there, you mentioned you want to recursively take 10 elements at a time. It's very easy to do this iteratively, but to specifically do it recursively as you've asked is easy, too:

    my @sorted = ('A'..'Z'); # probably sort keys %some_hash; reduce(@sorted); sub reduce { my @ten = splice(@_, 0, 10); return if (!@ten); # Base case # return if (@ten < 10); # Or do you want to stop if < 10 elements +? print join(',',@ten) . "\n"; return reduce(@_); # Recursion case, remainder of array }

    Have a look at this page on recursion if you need to brush up on your recursion theory. For example, you can switch the recursion case and the processing step, and of course you may want to return a value derived from your computations on @sorted. I leave these as an exercise to the OP. :-)

Re: recursively reduce an array
by johngg (Canon) on Nov 06, 2012 at 11:58 UTC

    If you are sorting on values, do you mean something like this?

    use strict; use warnings; use feature qw{ say }; sub groupsOf (&$@); my %hash = map { $_ => int rand 50 } q{a} .. q{z}; say qq{$_\n-----} for groupsOf { join qq{\n}, map { qq{$_ => $hash{ $_ }} } @_ } 10, sort { $hash{ $a } <=> $hash{ $b } } keys %hash; sub groupsOf (&$@) { my $rcToRun = shift; my $groupsOf = shift; my $rcDoIt; $rcDoIt = sub { $rcToRun->( map shift, 1 .. ( @_ < $groupsOf ? @_ : $groupsOf ) ), @_ ? &$rcDoIt : (); }; &$rcDoIt; }

    The output.

    $ ./spw1002389 n => 0 t => 2 w => 5 g => 8 d => 16 b => 16 c => 18 j => 20 o => 22 h => 23 ----- y => 25 k => 28 i => 29 q => 29 s => 30 x => 31 u => 34 l => 34 p => 34 m => 36 ----- f => 38 v => 38 r => 43 a => 43 e => 49 z => 49 ----- $

    I hope this is heading in the right direction but please ask further if we have misunderstood your problem.

    Cheers,

    JohnGG