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

Fellow Monasterians,

First, apologies for that convoluted title.

Here's the scenario:

So:

my $AoH = [ { name => "Bob", gender => "M" }, { name => "Sue", gender => "F" }, { name => "Mike", gender => "M" } ];

And then magically:

my $template->param( men => all pairs where $AoH{gender] eq "M", women => all pairs where $AoH{gender] eq "F" );
Loop code I would normally use:
my ($men, $women); my $m = 0; my $w = 0; for my $i ( 0 .. $#$AoH ) { if ($AoH->[$i]{gender} eq "M") { $men->[$m] = $AoH->[$i]; $m++; } else { $women->[$w] = $AoH->[$i]; $w++; } } my $template->param( men => $men, women => $women );

Just looking for a cleaner way to do this. Thanks!


—Brad
"The important work of moving the world forward does not wait to be done by perfect men." George Eliot

Replies are listed 'Best First'.
Re: Assigning AoH pairs by value other AoH's
by Tanktalus (Canon) on Sep 10, 2005 at 17:55 UTC
    my $template->param( men => [ grep { $_->{gender} eq 'M' } @$AoH ], women => [ grep { $_->{gender} eq 'F' } @$AoH ], );

    Given the phrasing of the question, I think this maps very closely to the way you are asking the question. Granted, it scans through your @$AoH twice, which makes it a little less efficient than other methods, but it does map very closely to the way you are thinking of your problem by what you asked.

      Took this route because in practice the actually script was more complicated than my example. It worked great. I appreciate the example of using grep within $template->param. Another trick in my bag.


      —Brad
      "The important work of moving the world forward does not wait to be done by perfect men." George Eliot
Re: Assigning AoH pairs by value other AoH's
by pg (Canon) on Sep 10, 2005 at 17:50 UTC

    The basic structure of your code is efficient as it only loops throught the AoH once (you sort of described it as twice, but in fact once). To loop through twice is not a good idea for performance, if things can be done within one loop. Just to make that loop a little bit simpler.

    use Data::Dumper; my $AoH = [ { name => "Bob", gender => "M" }, { name => "Sue", gender => "F" }, { name => "Mike", gender => "M" } ]; my ($men, $women); map {(push @{($_->{"gender"} eq "M") ? $men : $women}, $_)} @$AoH; print Dumper($men); print Dumper($women);

    Side note: even with your code, there was no need for you to remember the last index of the arrays. You can always push, or use $#array, so $m and $w can be removed.

Re: Assigning AoH pairs by value other AoH's
by nedals (Deacon) on Sep 10, 2005 at 22:25 UTC

    Depending on how you want the data displayed, you might consider using HTML::Templates's LOOP function by changing the gender to 1 and 0 instead of 'M' and 'F'

    my $AoH = [ { name => "Bob", gender => 1 }, { name => "Sue", gender => 0 }, { name => "Mike", gender => 1 } ]; $template->param( ARRAY => $AoH, ); .tmpl file... <TMPL_LOOP NAME=ARRAY> <!-- males --> <TMPL_IF NAME="gender"><TMPL_VAR NAME=name> .... <TMPL_ELSE> <!-- females --> <TMPL_VAR NAME=name> <TMLP_IF> </TMPL_LOOP>