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

This node falls below the community's threshold of quality. You may see it by logging in.

Replies are listed 'Best First'.
Re: foreach problem
by Abigail-II (Bishop) on May 18, 2004 at 14:33 UTC
    Well, your problem seems to come from the fact that foreach file, you print 4 buttons. So you have 4 times as many buttons as you have files - no wonder you get duplicates. Do something like:
    print start_from (...); print table (...); s/*[\/\\](.*)/$1/ for @files; while (@files >= 4) { print Tr ({...}, map {td (submit (-name => 'file', -value => $_))} + splice @files => 0, 4); } print Tr ({...}, (map {td (submit (-name => 'file', -value => $_))} @f +iles), map {td ()} 1 .. (4 - @files)) if @files

    Abigail

Re: foreach problem
by sgifford (Prior) on May 18, 2004 at 14:33 UTC
    The problem is that all four buttons are inside the same loop iteration, so $_ is set to the same thing all four times you call it. What you want is something like this (untested):
    my @cols = (); foreach (@files) { $_ =~ s/.*[\/\\](.*)/$1/; push(@cols,td(submit(-name => 'file', -value => $_)); if (@cols == 4) { print Tr({-alien => 'center'}, @cols); @cols=(); } } if (@cols) { while (@cols < 4) { push(@cols,td('&nbsp;')); } print Tr({-alien => 'center'}, @cols); }
    That builds up a row, and prints it when it's finished. For the last row, it creates cells with a single non-breaking space in them, which avoids formatting annoyances in some browsers.
Re: foreach problem
by punkish (Priest) on May 18, 2004 at 14:32 UTC
    This is happening because the special var $_ is referring to the array element received in a particular for loop. What you really want is an array of 4-element arrays for the buttons. Then you can have a foreach inside another foreach...

    foreach my $thesebuttons (@aoa) { my @b = @$thesebuttons; foreach my $thisbutton (@b) { code for printing out this button... } }
    A reply falls below the community's threshold of quality. You may see it by logging in.
Re: foreach problem
by sacked (Hermit) on May 18, 2004 at 14:43 UTC
    In each iteration of your foreach loop, $_ is set to one value in @files. As your call to Tr is inside the foreach loop, $_ has the same value in each td. You can use map to iterate over the list of files and get the results you want. Also, note the use of File::Basename::basename instead of a regular expression to remove the directory from the filenames:
    use File::Basename; # ... # 4 elements at a time while( my @cols= splice @files, 0, 4 ) { print Tr( {-align=>'center'}, map { td( $_ ? submit(-name=>'file', -value=> basename($_)) : '&nbsp;' + ) } @cols[0..3] ); }
    Or, use the distributive properties of the HTML shortcuts provided by CGI.pm (see the pod). In this case, we are passing a reference to a list of values to td, rather creating a list of calls to td:
    use File::Basename; # ... while( my @cols= splice @files, 0, 4 ) { print Tr( {-align=>'center'}, td([ map { $_ ? submit(-name=>'file', -value=> basename($_)) : '&nbsp;' } @cols[0..3] ]) ); }

    --sacked
    A reply falls below the community's threshold of quality. You may see it by logging in.
Re: foreach problem
by Roy Johnson (Monsignor) on May 18, 2004 at 18:39 UTC
    You might find this easy to understand:
    for(my $x=0; $x<$#files+4; $x+=4) { @four_files = @files[$x..$x+3]; print Tr( {-align=>'center'}, td( submit(-name=>'file', -value=>$f +our_files[0] )), td( submit(-name=>'file', -value=>$f +our_files[1] )), td( submit(-name=>'file', -value=>$f +our_files[2] )), td( submit(-name=>'file', -value=>$f +our_files[3] ))); }

    The PerlMonk tr/// Advocate