Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Wanet Telecoms Ltd on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Shorten script

Status
Not open for further replies.

uniopp

Technical User
Oct 7, 2001
152
JP
Hi,
Can anyone show me how to shorten the following snipit of code?
There must be a way to do it without having all the elsif clauses repeating the same html.
@addresses contains from 0 to 40 table columns like -
<td width=\"215\" align=\"center\" valign=\"middle\"><img src=$image_address></td>
but the number of columns varies each time and may not always be an even number.
I want to end up with 2 images and the two spacing columns in each row (except for the last if we have an odd number).
Any help would be most appreciated.
Thank you.

>>> Code Snipit Start <<<
$number_of_columns=@addresses;

#for each two colums in @addresses generate one complete table row

if (($number_of_columns==1) || ($number_of_columns==2)) {
$output=<<PICTURE_LESSON;
<tr>
$addresses[0]
<td width="5">&nbsp;</td>
$addresses[1]
<td width="5">&nbsp;</td>
</tr>
PICTURE_LESSON
return $output;
}

elsif (($number_of_columns==3) || ($number_of_columns==4)){
$output=<<PICTURE_LESSON;
<tr>
$addresses[0]
<td width="5">&nbsp;</td>
$addresses[1]
<td width="5">&nbsp;</td>
</tr>
<tr>
<td width="215">&nbsp;</td>
<td width="5">&nbsp;</td>
<td width="215">&nbsp;</td>
<td width="5">&nbsp;</td>
</tr>
<tr>
$addresses[2]
<td width="5">&nbsp;</td>
$addresses[3]
<td width="5">&nbsp;</td>
</tr>
PICTURE_LESSON
return $output;
}


# etc. etc. for up to 20 table columns

else {
$output=<<PICTURE_LESSON;
<tr>
<td width="215">&nbsp;</td>
<td width="5">&nbsp;</td>
<td width="215">&nbsp;</td>
<td width="5">&nbsp;</td>
</tr>
PICTURE_LESSON
return $output;
}

>>> Code Snipit End <<<
 
OK, I did it with the code below but I'm not sure how to handle it if there is an odd number because it will cause $number_of_columns not to be a whole number (e.g 6.5). How do I get it to round up to the next whole number?

Note: I changed it so @addresses only contains the image name and not the html code as well.

>>> Code Snipit Start <<<
$number_of_columns=@addresses;
#divide $number_of_columns by 2
$number_of_columns=$number_of_columns/2;
my $count=1;
my $column_1=0;
my $column_2=1;
while ($count<=$number_of_columns) {
$output.=<<PICTURE_LESSON;
<tr>
<td width="215" align="center" valign="middle">
<img src=$addresses[$column_1]></td>
<td width="5">&nbsp;</td>
<td width="215" align="center" valign="middle">
<img src=$addresses[$column_2]></td>
<td width="5">&nbsp;</td>
</tr>
<tr>
<td width="215" height="5"></td>
<td width="5" height="5"></td>
<td width="215" height="5"></td>
<td width="5" height="5"></td>
</tr>
PICTURE_LESSON

$count++;
$column_1=$column_1+2;
$column_2=$column_2+2;
}
return $output;


>>> Code Snipit End <<<
 
I got it to work by adding -
$number_of_columns=$number_of_columns+0.5;
but I'm sure there is a better way of doing it.
Any advice would be much appreciated.
Thank you.
 
I probably would have tried
$column=0;

$addresses[$column], $addresses[++$column];
$column++;

But you'd need to check for out of bounds on the last line

Also
Code:
   <tr>
    <td width="215" height="5"></td>
    <td width="5" height="5"></td>
    <td width="215" height="5"></td>
    <td width="5" height="5"></td>
   </tr>
could be
Code:
   <tr>
     <td colspan=4 height=5 width=440>&nbsp;</td>
   </tr>
or
Code:
   <tr>
     <td colspan=4 height=5>&nbsp;</td>
   </tr>
because the width should be inherited from the column widths above

--Paul

cigless ...
 
Thanks Paul,
I understand what you said about the html table code but I'm not sure about the first part as I still think I will have a problem with odd numbers.
There must be a way to check if a number is not whole and round it up to the next whole number.
Anyone have any ideas.
Thank you.
Simon.
 
using some dumbed up table cell data, this method seems to work OK:

Code:
#!perl
use CGI qw/:standard/;
use warnings;
use strict;
print header;

my @addresses =();
my $test = 0;
for (0 .. 26) {
   $test++;
   $addresses[$_] = "cell: $test";
}
#print "@addresses";
my $odd = 0;
if (int(@addresses) % 2) {$odd = 1;}#for odd number of table cells
my $table_spacer = "<tr><td colspan=4>&nbsp;</td></tr>";

print qq~<table border=1>\n~;
&get_rows(@addresses);
print qq~</table>~;

sub get_rows {
   my @temp = @_;
   my $output;
   for my $i (0 .. $#temp) {
      my $flag = 0;
      $flag = 1 if ($i % 2 == 0);#indicates new row
      $output .= '<tr>' if ($flag == 1);
      $output .= qq~<td width="215" align="center" valign="middle">index # $i : $temp[$i]</td><td width="5">&nbsp;</td>~;
      next if ($flag == 1);
      $output .= qq~</tr>\n~ if ($flag == 0);
      $output .= $table_spacer if ($i < $#temp);
   }
   $output .= qq~<td width="215" align="center" valign="middle">filler cell</td><td width="5">&nbsp;</td></tr>\n~ if $odd == 1;  
   print $output;
}

You should be able to adapt it to your script if you wanted to.
 
Thanks KevinADC,
I'll give it a try.
As I said, it is working the way I had it but I was wondering if my code had any potential problems?
Simon.
 
well, there could be a small problem. Your script looks like it will print one row too many for even numbered entries, or one cell too few for odd numbered entries. Even if you round up the $number_of_cells, your script will print the extra empty row on the bottom of the table. That might or might not be a problem.
 
Awk
Code:
BEGIN {
  # Make dummy data.
  for (i=1; i<6; i++)
    addresses[i] = cell( "cell: " i, 215 )

  print make_table( addresses )
}

function make_table( addresses   ,number_of_columns,output,i)
{ number_of_columns = length(addresses)
  if (0==number_of_columns)
    output = empty_row()
  else
  { output = ""
    for (i=1; i<=number_of_columns; i+=2)
    { if (i>1)
        output = output empty_row()
      output = output "<tr>\n" addresses[i] empty_cell(5)
      if (i<number_of_columns)
        output = output addresses[i+1] empty_cell(5)
      else
        output = output cell_pair()
      output = output "</tr>\n"
    }
  }
  return output
}

function cell(text,n)
{ return "<td width=\"" n "\">" text "</td>\n" }
function empty_cell(n)
{ return cell("&nbsp",n) }
function cell_pair()
{ return empty_cell(215) empty_cell(5) }
function empty_row()
{ return "<tr>\n" cell_pair() cell_pair() "</tr>\n" }
 
uniopp

The following does what the code in your original post does (I think), and it's shorter as requested. I haven't implemented PaulTEGs suggestions re: shortening the HTML, but I guess that would help too. It avoids awkward calculations by adding a dummy entry to the list if it has an odd number of elements.
Code:
use strict;
use warnings;

my $output;
my @addresslist = ( "address 0", "address 1", "address 2", "address 3", "address 4");

push @addresslist, "&nbsp;" if (@addresslist % 2); # even up the list

for (my $i = @addresslist / 2; $i > 0; $i--) {
    $output .= qq[<tr>\n] . shift(@addresslist) 
       . qq[<td width="5">&nbsp;</td>\n] . shift(@addresslist) 
       . qq[<td width="5">&nbsp;</td>\n</tr>\n];
    $output .= qq[<tr>\n<td width="215">&nbsp;</td>\n<td width="5">&nbsp;</td>\n<td width="215">&nbsp;</td>\n<td width="5">&nbsp;</td>\n</tr>\n]
       unless ($i == 1);
}
print "$output";
This does a 'destructive read' of the array because of the shift statements - if this is a problem, copy it to another array first.

HTH
 
Thanks stevexff,
That's much shorter!!!
I'll give it a try.
Thank you.
 
Sometimes "shorter" is not necessarily better.
I often like longer code if its easier to read.
And avoid the quip "Perl. Write once, read never".
 
Agreed. It does actually look a bit better in my editor without the word wrapping, but I don't like here-documents and the large number of literals make it ugly and hard to read. How about
Code:
use strict;
use warnings;

my $output;
my @addresslist = (<DATA>);
chomp @addresslist;

push @addresslist, "&nbsp;" if (@addresslist % 2); # even up the list

while (@addresslist) {
    $output .= writerow(shift @addresslist, shift @addresslist);
    $output .= writerow("&nbsp;", "&nbsp;") unless (@addresslist < 3);
}
print "$output";

sub writerow {
    my $c1 = shift;
    my $c2 = shift;
    my ($w1, $w2) = (215, 5); # column widths
    my $row  = "<tr>\n" . writecolumn($c1, $w1) . writecolumn("&nbsp;", $w2);
    $row .= writecolumn($c2, $w1) . writecolumn("&nbsp;", $w2) . "</tr>\n>";
    return $row;
}
sub writecolumn {
    my $value = shift;
    my $w = shift;
    $value = qq[<img src="] . $value . qq[">] unless $value eq "&nbsp;";
    my $h = 5; # row height
    return qq[<td width="$w" align="centre" valign="middle" height="$h">$value</td>\n];
}
    
__DATA__
urlone
urltwo
urlthree
urlfour
urlfive
instead? It does more (treats the <img> tags properly, allows you to vary the table row & column sizes easily) and is maybe easier to read. It's not as short, though...
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top