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

Mirthful Monks,

I've been having a ball creating fun iterative structures in Template Toolkit templates - and then ran into this.

Users, identified by their user_type, last name (lname), and company, make selections numbered 1 to 6. They can make multiple selections. I receive their selections as a string:

$choices = ",1,2,3,4,5,6,";
For other purposes in the script, I build a hash-based data structure out of all of it:
$data{$user_type}{$user_company}{$user_lname}{'attribute'}

To store their choices, I split the string into an array, and store the array in a 'choice_list' attribute of that user:

$data{$user_type}{$user_company$}{$user_lname}{'choice_list'} = [ @spl +it_list ];
And at one point I want to output a list of choices for each user, grouped by lname, then by company, then by user_type (hence the data structure).

Everything was going perfectly until I added the very last loop to iterate over the choices array:

Perl script snippets:

$choices = ",1,2,3,4,5,6,"; print "Perl script output - <br>choices list before regex = $choices\n +"; #string cleanup $choices =~ s/^,//; $choices =~ s/,$//; print "<br>choices list after regex = $choices\n"; @split_list = split(/,+/, $choices); # debugging output to check split for $i (0 .. $#pub_list) { print "<br>choice $i = $pub_list[$i]\n"; } $data{$user_type}{$user_company$}{$user_lname}{'choice_list'} = [ @spl +it_list ]; $vars = { data => \%data, }; $template->process($template_file, $vars);

Template:

Template output - <br>Choices are:<br> [% FOREACH type IN data.keys.sort %] [% FOREACH company IN data.$type.keys.sort %] [% FOREACH name IN data.$type.$company.keys.sort %] [% FOREACH choice IN data.$type.$company.$name.choice_l +ist %] [% data.$type.$company.$name.choice_list.$choice % +]<br> [% END %] [% END %] [% END %] [% END %]

Output:

Perl script output - <br>choices list before regex = ,1,2,3,4,5,6, <br>choices list after regex = 1,2,3,4,5,6 <br>choice 0 = 1 <br>choice 1 = 2 <br>choice 2 = 3 <br>choice 3 = 4 <br>choice 4 = 5 <br>choice 5 = 6 Template output - <br>Choices are:<br> 2<br> 3<br> 4<br> 5<br> 6<br> <br>
I have the right number of breaks in the output, but the choice numbers are shifted - the "1" is missing and there's an extra break after the 6. Is it something to do with the way that I'm referencing the array of choices?

Thanks.

Updated within 60 seconds of original posting, and before any replies, for typo in template loops




Forget that fear of gravity,
Get a little savagery in your life.

Replies are listed 'Best First'.
Re: Iterating over hash of arrays in Template Toolkit
by kyle (Abbot) on Apr 10, 2007 at 16:03 UTC

    In the innermost loop of the template, choice takes on the value of each of the list elements, but you're using it as an index instead. Try this:

    [% FOREACH choice IN data.$type.$company.$name.choice_list %] [% choice %]<br> [% END %]
      Great minds think alike - you beat me to it by the time it took me to type it -thanks.




      Forget that fear of gravity,
      Get a little savagery in your life.
Re: Iterating over hash of arrays in Template Toolkit
by punch_card_don (Curate) on Apr 10, 2007 at 16:07 UTC
    Found it.

    In the central Template loop

    [% FOREACH choice IN data.$type.$company.$name.choice_list %] [% data.$type.$company.$name.choice_list.$choice %]<br> [% END %]
    of course, since we're dealing in this loop with an array and not a hash, 'choice' pulls out the value stored in the array, not the hash key like in the previous loops. I was referring to the index of the array element with the value in the elements - which go from 1 to 6, not 0 to 5.

    The correct format was

    [% FOREACH choice IN data.$type.$company.$name.choice_list %] [% choice %]<br> [% END %]
    which gives me the correct output.

    Thanks.




    Forget that fear of gravity,
    Get a little savagery in your life.
Re: Iterating over hash of arrays in Template Toolkit
by philcrow (Priest) on Apr 10, 2007 at 15:46 UTC
    I think you've run into a zero offset vs. one offset. Your choice list is 1-6, perl numbers the array 0-5.

    Phil

    The Gantry Book is now available.
      You mean a Template Toolkit "FOREACH" iterates over an array counting from 1, whereas Perl does it counting from 0?




      Forget that fear of gravity,
      Get a little savagery in your life.