Summary

This came about for 2 reasons.
Firstly, someone asked about dumping an array of arrays into an html table. The basics of doing that are easy enough, but I've included a few extra options for my own projects - optional borders and table headers as well as verifying each array has the same number of members. The final step came from some customer reports. They listed things by row, rather than by column. A quick search through PM didn't show anything useful, so I whomped up some code that did the trick. Aside from the fact that it only prints the array, it looks a lot like C :
for($x=0; $x<3;$x++){ for($y=0; $y<3;$y++){ print $lines[$y][$x], " "; } }
And while it was functional, I wanted to find the inner JAPH within. So I thought for a while, and developed the following snippet :

map { my $x=0; map { push @{$foo[$x]}, $_; $x++; } @$_; } @lines;
Not bad! Though, I can't help but think that the $x is really, in some secret way, horribly redundant. Plus, using braces to reference arrays hurts my head.
So, with all that in mind, I present the following program, which presents and tests make_table_from_AoA. Please note that it should die on the fourth test; this is not an error.
#!/usr/bin/perl use CGI::Pretty qw(:standard); # import CGI objects and fu +nctions use CGI::Carp qw(fatalsToBrowser); @a= ( ["Food","Price","Check to order","1/2 off one item"], ["burger","\$2.00",checkbox ("One of these"),radio_group (-name=> +"half off bonus", -value =>1)], ["chicken","\$2.50",checkbox ("and one of these, too"),radio_grou +p (-name=>"half off bonus",-value =>2)], ["tofutii","\$1.75",checkbox ("and one of them, while we're at it +."),radio_group (-name=>"half off bonus",-value =>3)], ); @b= ( ["Fruit" ,"Kiwi" , "Tangerine" , "Mango" , "Pom +elo","Carambola"], ["Origin" ,"New Zealand" , "Florida" , "Venezuela" , "Mex +ico","Arizona"], ["Color" ,"Brown" , "Orange" , "Red & Green" , "Yel +low"] ); print header(); print start_html(); &make_table_from_AoA (1,0,1,0,@a); print p,hr,p; &make_table_from_AoA (1,1,1,4,@a); print p,hr,p; &make_table_from_AoA (0,0,0,2,@b); print p,hr,p; &make_table_from_AoA (1,1,1,1,@b); #################### # # make_table_from_Aoa # # parameters # 1) $use_th : if this is true, the first line of the passed array +will be used # as an HTML header. # 2) $transpose : swap axis of array # 3) $check_array_size : if true, make sure each array has same # o +f elements # 4) $border : size of border to put around table. # 5) @l_array : holding tank for passed array. # #################### sub make_table_from_AoA { local $use_th = shift; local $transpose = shift; local $check_array_size = shift; local $border = shift; local @l_array = @_; #Make sure arrays are the same size. if not, die. if ($check_array_size){ $size =scalar(@{$l_array[0]}); map {die "funky arrays : First array is $size, found one of " +.scalar(@{$_}) if scalar(@{$_}) != $size}@l_array; } if ($transpose) { local @tary; map {my $x=0; map {push @{$tary[$x]}, $_;$x++;} @$_; } @l_array; @l_array=@tary; } print table( {-border=>$border}, $use_th?th([@{shift @l_array}]):undef, map{Tr(map{td($_)}@$_)}@l_array ); }

Replies are listed 'Best First'.
Re: transpose AoA and HTML table AoA contents.
by salvadors (Pilgrim) on Jan 12, 2001 at 02:24 UTC

    A few comments on this.

    Firstly, when you're going to do a nested map like that, I don't think there's a lot of ways around using a temporary variable if you need to access $_ from both maps. If there is I'd like to know it, as I've had to do some of this recently. Perhaps someone with a more functional background can show a few cool tricks here?

    Secondly, you don't want to be using local so much. You want "my" instead. You can read the reasons why at Dominus' great Coping With Scoping article.

    Also, you don't need to use the double map to print your HTML. From the manual for CGI:

    THE DISTRIBUTIVE PROPERTY OF HTML SHORTCUTS
    
    One of the cool features of the HTML shortcuts is that they
    are distributive.  If you give them an argument consisting of
    a reference to a list, the tag will be distributed across each
    element of the list.
    

    So, instead of print table(map{Tr(map{td($_)}@$_)}@l_array) you can just use

    print table( Tr([ map { td([ @$_ ]) } @a ]) );

    Tony

      ++ for salvadors. The table-print can be made shorter, though:
      print table( Tr( map { Td( $_ ) } @a ) );
      Since you don't need to dereference anything with CGI. But I didn't know that until I grogged that manual-quote by your posting. Thanks!

      Jeroen
      I was dreaming of guitarnotes that would irritate an executive kind of guy (FZ)