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

Hello Samar! Thank you - yes that's exactly what I want to do. With the current code, the output looks somewhat like this:
date user1 user2 user3 user4 user5 day1 dl1 dl2 dl3 dl4 dl5 day2 dl1 dl2 dl3 dl4 dl5 dl6 dl7..dl10 day3 dl1 dl2 dl3 dl4 dl5 dl6 dl7..dl15
This is what I want:
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 would be the perl code to skip the first 5 iterations of the second loop and first 10 of the third loop? Adapting that code to the template is quite easy, so that wouldn't be the problem. Thank you for your help! :-) Regards Fred

Replies are listed 'Best First'.
Re^3: How to skip certain values in a foreach loop
by Frederic_S (Novice) on Dec 28, 2010 at 13:09 UTC
    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

      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

      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