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

Fellow monasterians,

I'm not sure whether I'm trying to sort an AoHoH or AoHoAoH, but I want to end up with an AoH ref for an HTML::Template loop that is sorted by month and then date, like:

July 12 golfing 20 retreat 29 marathon August...

Here's what I have now, but am getting different errors depending on how I treat the dereferencing in the "@s2_events" line, but the first sort (by month) is working.

#!/usr/bin/perl print "Content-type: text/plain\n\n"; use strict; use warnings; use CGI::Carp qw(fatalsToBrowser); use Data::Dumper; my $events = [ { month => 8, name => "August", list => [ { name => "retreat", date => 20 }, { name => "marathon", date => 29}, { name => "golfing" , date => 12} ] }, { month => 7, name => "July", list => [ { name => "high tea", date => 15 }, { name => "rafting" , date => 23 }, + { name => "picnic", date => 10 }, ] }, ]; my @s1_events = sort { $a->{month} <=> $b->{month} } @$events; print Dumper (@s1_events); my @s2_events = sort { $a->{list}{date} <=> $b->{list}{date} } @s1_eve +nts; print Dumper(@s2_events); #produces 'pseudo-hashes are deprecated error'

I've spent hours searching and haven't found anything that handles this complexity, so here I am back at the monastery. Thanks all.


—Brad
"Don't ever take a fence down until you know the reason it was put up. " G. K. Chesterton

Replies are listed 'Best First'.
Re: Sorting an AoHoH or AoHoAoH
by broquaint (Abbot) on Jun 23, 2004 at 03:04 UTC
    A straightforward solution is to sort at a finer granularity e.g
    use DDS; # your $events structure here ... @$events = sort { $a->{month} <=> $b->{month} } @$events; @{$_->{list}} = sort { $a->{date} <=> $b->{date} } @{$_->{list}} for @$events; Dump $events; __output__ $ARRAY1 = [ { list => [ { date => 10, name => 'picnic' }, { date => 15, name => 'high tea' }, { date => 23, name => 'rafting' } ], month => 7, name => 'July' }, { list => [ { date => 12, name => 'golfing' }, { date => 20, name => 'retreat' }, { date => 29, name => 'marathon' } ], month => 8, name => 'August' } ];
    HTH

    _________
    broquaint

Re: Sorting an AoHoH or AoHoAoH
by Ido (Hermit) on Jun 23, 2004 at 03:13 UTC
    Your second sort phase should sort different lists. In order to do that you should sort more than once. Also, please notice that every element of @s1_events is a hashref, and the 'list' element of the hashref is an arrayref, not another hash. Therefore, you can't $a->{list}{date}.
    In order to sort each month's list, I would iterate through months, and sort, like:
    for(@s1_events){ @{$_->{list}}=sort {$a->{date}<=>$b->{date}} @{$_->{list}}; }
    Hth..
      Thanks broquaint and Ido for the nearly instant solution and explanation, helping me get my head around these complicated data structures. I Googled for hours, but found it here at the monastery in minutes. Thanks.

      —Brad
      "Don't ever take a fence down until you know the reason it was put up. " G. K. Chesterton
Re: Sorting an AoHoH or AoHoAoH
by bageler (Hermit) on Jun 23, 2004 at 03:06 UTC
    you could use a Schwartzian Transform, handy when you want to sort a multi dimensional data set by some subkey:
    my @s1_events = map { $_->[0] } sort { $a->[1] <=> $b->[1] } map {[$_, $_->{month}]} @$events;
    and then when you want to print do something like
    for my $ev (@s1_events) { my @sd = map {"\t$_->{date} $_->{name}\n"} sort {$a->{date} <=> $b->{date}} @{$ev->{list}}; print "$ev->{name}\n@sd\n"; }
      Using the Schwartzian Transform is very efficient when you want to do something with which element, and sort it by the result. In that case, generating a new list with items and their generated sorting "keys", lets you process each item only once, instead of many times.
      But, in this case, you sort by an element of a hash, and the sort in the Schwartzian Transform must sort by an element of an array, so there's no gain. Actually, you lose, both time and simplicity.
Re: Sorting an AoHoH or AoHoAoH
by markjugg (Curate) on Jun 23, 2004 at 16:40 UTC
    If by chance you are starting with DBI-accessed database and want to send the output to HTML::Template, then Data::Grouper may be just the tool you need.

    I'm doing a lot less complex data structure transformation since I discovered that.

      Wow, thanks markjugg. It makes me just how many CPAN modules I could use and am not. Yes, Data::Grouper looks awesome. I spent days getting triple nested <TMPL_LOOP>'s to work. I'll look into this.

      —Brad
      "Don't ever take a fence down until you know the reason it was put up. " G. K. Chesterton