Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Re^3: How to skip certain values in a foreach loop

by Frederic_S (Novice)
on Dec 28, 2010 at 13:09 UTC ( [id://879425]=note: print w/replies, xml ) Need Help??


in reply to Re^2: How to skip certain values in a foreach loop
in thread How to skip certain values in a foreach loop

Maybe I should also elaborate where I get the data from. This is how the data is fetched and proccessed:
# In the main script: my @ReturnValues; my @AdminValues; my @AdminTime; my @AdminEndDate; Admin(\@ReturnValues, \@AdminValues, \@AdminTime, \@AdminEndDate); # This is the code in sub Admin: my $sql = "SELECT DISTINCT user_id, realname FROM database.time_data W +HERE version='$Version' AND product_id='$ProductID' AND milestone='$M +ileStone'"; my $sth = $dbh->prepare($sql); $sth->execute(); while(my @RowAdmin = $sth->fetchrow_array()) { my %AdminData; $AdminData{"UserID"} = $RowAdmin[0]; $AdminData{"RealName"} = $RowAdmin[1]; # Insert them into hash push (@$AdminValues, \%AdminData); } # Get the stored days $sql = "SELECT DISTINCT day FROM database.time_data WHERE version='$Ve +rsion' AND product_id='$ProductID' AND milestone='$MileStone'"; $sth = $dbh->prepare($sql); $sth->execute(); while(my @RowTime = $sth->fetchrow_array()) { my %AdminTimeData; $AdminTimeData{"Day"} = $RowTime[0]; push (@$AdminTime, \%AdminTimeData); my $sql2 = "SELECT app_end FROM database.time_data WHERE day='$AdminTi +meData{'Day'}' AND version='$Version' AND product_id='$ProductID' AND + milestone='$MileStone'"; my $sth2 = $dbh->prepare($sql2); $sth2->execute(); while(my @RowTime2 = $sth2->fetchrow_array()) { my %AdminAppEnd; $AdminAppEnd{"AppEnd"} = $RowTime2[0]; push (@$AdminEndDate, \%AdminAppEnd); } } $sth->finish(); $dbh->disconnect(); # Back in the main script: # Pass Values to template $vars->{'ReturnValues'} = \@ReturnValues; $vars->{'AdminValues'} = \@AdminValues; $vars->{'AdminTime'} = \@AdminTime; $vars->{'AdminEndDate'} = \@AdminEndDate;
How the data is then proccessed in the template can be seen in the first Post. I hope this helps a bit. Regards Fred

Replies are listed 'Best First'.
Re^4: How to skip certain values in a foreach loop
by Anonyrnous Monk (Hermit) on Dec 28, 2010 at 14:32 UTC

    I think it would make your life easier if you would massage your date into a more appropriate form on the Perl side, instead of fighting with slices of linear arrays within the template.

    Here's a simplified example showing a possible data structure:

    #!/usr/bin/perl -w use strict; use Template; my $templ = q{ <table> <tr> <td>date</td> [% FOREACH realname IN Users %] <td>[% realname %]</td> [% END %] </tr> [% FOREACH row IN Dates %] <tr> <td>[% row.Day %]</td> [% FOREACH date IN row.EndDates %] <td>[% date %]</td> [% END %] </tr> [% END %] </table> }; my $vars = { Users => [qw(user1 user2 user3 user4 user5)], Dates => [ { Day => 'day1', EndDates => [qw(dl1 dl2 dl3 dl4 dl5)], }, { Day => 'day2', EndDates => [qw(dl6 dl7 dl8 dl9 dl10)], }, { Day => 'day3', EndDates => [qw(dl11 dl12 dl13 dl14 dl15)], }, ], }; my $tt = Template->new(); $tt->process(\$templ, $vars) or die $tt->error();

    Output:

    date user1 user2 user3 user4 user5
    day1 dl1 dl2 dl3 dl4 dl5
    day2 dl6 dl7 dl8 dl9 dl10
    day3 dl11 dl12 dl13 dl14 dl15
      Thank you Mr. Anonymous Monk ;-)

      The idea you had is surely great when being able to define the template structure used yourself. Unfortunatly, I'm forced to use what the Bugzilla Crew gives me to work with :-(
      What I'm programming is an addon for my company for Bugzilla.

      I've been able to modify the code so far, that the users are selected from the database and written into an array. the code looks like this:
      --> in the external module, embedded in a sub: # Get user realnames for project my $sql = "SELECT DISTINCT realname FROM database.time_data WHERE vers +ion='$Version' AND product_id='$ProductID' AND milestone='$MileStone' +"; #user_id, my $sth = $dbh->prepare($sql); $sth->execute(); while(my @RowAdmin = $sth->fetchrow_array()) { push (@$AdminUsers, $RowAdmin[0]); } my $vars2 = { Users => [@$AdminUsers], Dates => [ { Day => 'day1', EndDates => [qw(dl1 dl2 dl3 dl4 dl5)], }, { Day => 'day2', EndDates => [qw(dl6 dl7 dl8 dl9 dl10)], }, { Day => 'day3', EndDates => [qw(dl11 dl12 dl13 dl14 dl15)], }, ], }; return($vars2); --> in the main script (buglist.cgi): # call subroutine my $vars2 = Admin(\@ReturnValues, \@AdminUsers); # pass results to template $vars->{'vars2'} = $vars2; --> in the template (table.html.tmpl): <table class=table> <tr class="[% loop.parity %]"> <td class=title_td colspan=6>Coordinator overview:</td> </tr> <tr class="[% loop.parity %]"> <td class=title_td>date</td> [% FOREACH realname IN vars2.Users %] [% FOREACH realname IN realname %] <td class=title_td>[% realname %]</td> [% END %] [% END %] </tr> [% FOREACH row IN vars2.Dates %] <tr class="[% loop.parity %]"> <td class=var_td>[% row.Day %]</td> [% FOREACH date IN row.EndDates %] <td class=var_td>[% date %]</td> [% END %] </tr> [% END %] </table>
      Output: date user1 user2 user3 user4 user5 day1 dl1 dl2 dl3 dl4 dl5 day2 dl6 dl7 dl8 dl9 dl10 day3 dl11 dl12 dl13 dl14 dl15 What I don't quite see yet, is how I can get the days and the deadline part to be automated. I don't know how many days there are in the database and each day, a new dataset is added to the database and maybe there will be more than 5 users on a project at any time, so I have to somehow get the results I select from the database into the code you showed (wow, that rhymes). Embedding a while loop in the Dates=> part isn't possible, that was my first idea. So I would somehow have to rebuild the code, in order to automate the whole thing. I've only been programming in Perl for 4 weeks now so, to tell the truth, I'm a bit overstrained with the rebuilding needed here.
      What would I need to do, to keep the output the same, but change the way it's processed beforehand to arrays or hashes?
      Really sorry so being so helpless :-(

      Regards

      Fred

        My main point was that it's much easier to transform your data with Perl, than to cope with data structures that are suboptimal for the template in question on the Template Toolkit side.  Perl is a very powerful general purpose programming language, while the Template Toolkit mini language is special purpose and (deliberately) limited in features — otherwise you might as well directly embed Perl code into the HTML template... (as some other templating systems do, btw).

        In other words, to transform a linear array of deadlines (as you seem to get from your db query) into a more appropriate structure, you could do something like this:

        #!/usr/bin/perl -w use strict; my @dls = 'dl01'..'dl20'; # what you start out with my $nusers = 5; my $vars; for (my $i = 0; $i < @dls; $i += $nusers) { push @{ $vars->{Dates} }, { EndDates => [ @dls[$i..$i+$nusers-1] ] }; } use Data::Dumper; print Dumper $vars; __END__ $VAR1 = { 'Dates' => [ { 'EndDates' => [ 'dl01', 'dl02', 'dl03', 'dl04', 'dl05' ] }, { 'EndDates' => [ 'dl06', 'dl07', 'dl08', 'dl09', 'dl10' ] }, { 'EndDates' => [ 'dl11', 'dl12', 'dl13', 'dl14', 'dl15' ] }, { 'EndDates' => [ 'dl16', 'dl17', 'dl18', 'dl19', 'dl20' ] } ] };

        This is just an example, which you'd have to tailor to your circumstances, like adding the Day entries, etc.

Re^4: How to skip certain values in a foreach loop
by samarzone (Pilgrim) on Dec 28, 2010 at 14:31 UTC

    You should improve the structure of $vars. You have n values in @AdminTime and 5*n values in @AdminEndDate 5 for each value of @AdminTime. Right!!!
    You should keep only 5 values in @AdminEndDate, each an arrayref for all five deadlines of a day in @AdminTime. Now your @AdminEndDate array index will be same as that of @AdminTime.

    For example you have @AdminTime as ('day1', 'day2', 'day3') and @AdminEndDate as

    ({AppEnd => 'dl1'}, {AppEnd => 'dl2'}, {AppEnd => 'dl3'}, {AppEnd => 'dl4'}, {AppEnd => 'dl5'}, {AppEnd => 'dl6'}, {AppEnd => 'dl7'}, {AppEnd => 'dl8'}, {AppEnd => 'dl9'}, {AppEnd => 'dl10'}, {AppEnd => 'dl11'}, {AppEnd => 'dl12'}, {AppEnd => 'dl13'}, {AppEnd => 'dl14'}, {AppEnd => 'dl15'})

    Make your @AdminEndDate array like
    ([{AppEnd => 'dl1'}, {AppEnd => 'dl2'}, {AppEnd => 'dl3'}, {AppEnd => +'dl4'}, {AppEnd => 'dl5'}], [{AppEnd => 'dl6'}, {AppEnd => 'dl7'}, {AppEnd => 'dl8'}, {AppEnd => ' +dl9'}, {AppEnd => 'dl10'}], [{AppEnd => 'dl11'}, {AppEnd => 'dl12'}, {AppEnd => 'dl13'}, {AppEnd = +> 'dl14'}, {AppEnd => 'dl15'}]

    You can now run a loop from index 0 to $#AdminTime and use the index number for both the arrays. You'll, however, have to modify your template code a little to dereference the inner array references of all five values corresponding to each day

    --
    Regards
    - Samar

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://879425]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others imbibing at the Monastery: (9)
As of 2024-04-23 21:55 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found