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

Hi Monks, I have searched high and low on the perlmonks site for this, and I cant find anything (apologies If i missed it)

I have an @array with a list of categories, what I want to do is print this out in like a two column bullet point list, I thought this would use some kind of for loop, but im not sure..

Any ideas would be very helpfull

Replies are listed 'Best First'.
Re: Category List
by footpad (Abbot) on Dec 02, 2001 at 06:42 UTC

    I was going to hack up a couple of examples doing it the traditional way, however, I decided to take a quick peek in CPAN. Looks like you might be interested in Array::PrintCols (alt. link). There's a pretty clear example in the module's documentation.

    Just goes to show that there have been a lot of people using Perl over the years and that they've added just about everything you need to CPAN. Repeat after me: CPAN is your friend. :-)

    Update (for the reply): Forgive me, but I don't find that a very convincing excuse (especially when we have some fine tutorials that show how to install modules properly--and clearly.) Taken to the extreme, it's like saying..."Well, because some people are still using Perl versions older than 5.005_03, I won't distribute any code using CGI.pm." Which would be completely absurd, of course. While I've ranted on the topic from a different angle, I think someone else said it more eloquently. The bottom line is the same. Someone else has already done the hard work. Why reinvent the wheel?

    --f

      CPan is your friend......normally :)

      I want to avoid using too many modules as I need this script to be used on several servers, and its a little more convenient for the user if they dont need to install a module :(

      I really dont know how to approach this inside the script..
        If they are going to the trouble of installing your script on multiple machines, then you can just add the module in with your tarball and build your requires such that your script uses a local copy of the module rather than using the machine-wide modules. Other solutions would include cutting and pasting the necessary subs from the module to your script.

        As to the original question, you haven't said whether this is just splitting the data into two columns ( 1, 2; 3, 4; 5, 6; ) as you go over it or whether you want to go down the first column, then wrap to the second (1, 4; 2, 5; 3, 6 ).

        In the first case, you might consider a while loop using shift (make sure to copy the list, since shift will destroy it). In the second case, you need to split the list into two parts, then you can loop over the two half-lists by index.
Re: Category List
by cLive ;-) (Prior) on Dec 02, 2001 at 07:55 UTC
    Here's a cute little hack for you. You don't specify whether you want them sorting or what, but anyway:
    #!/usr/bin/perl -w use strict; # sorted list my @list = sort qw(stereo tv monitor scanner keyboard mouse banana); # add extra element if odd length, so next statement doesn't break push @list, '' if @list%2; # turn array into a hash my %list = @list; # text - need 'if' to avoid empty bullet if odd No. elements for (sort keys %list) { printf("- %-20s", $_); printf("- %-20s", $list{$_}) if $list{$_}; print "\n"; } # html (snippet) print qq(\n<table>\n); for (sort keys %list) { printf("<tr><td>%s</td><td>%s</td></tr>\n", $_, $list{$_}); } print qq(</table>\n);
    This sorts them left -> right, top -> bottom. If you want the precedence the other way round, you need to work on things a bit more.

    hth

    cLive ;-)

      You can avoid using a hash if you loop through @listnelements at a time, which has the added bonus of flexibility (for when you want to change the number of columns later on).

      #!/usr/bin/perl -wT use strict; my $columns = 2; # change this as needed my @list = sort qw(stereo tv monitor scanner keyboard mouse banana) +; while ( my @column = splice( @list, 0, $columns ) ) { printf "- %-20s", $_ foreach @column; print "\n"; # print TR( td( \@column ) ), "\n"; # CGI.pm-ized :-) }

          --k.


Re: Category List
by Purdy (Hermit) on Dec 02, 2001 at 07:31 UTC
    Well, I'm not sure if I'm following you correctly, but if you have an even amount of categories in your array, I would simply create a while loop, like so:

    my @categories = qw ( Horror Sci-Fi Comedy Action ); while ( @categories ) { my ( $oval ) = shift @categories; # odd value my ( $eval ) = shift @categories; # even value printf ("%15s %15s\n", $oval, $eval ); }

    You may also want to optimize that a bit and/or check out this node.

    Jason

      The first optimisation would be to make the script work correctly :). As things stands, 'Horror' is assigned to $_, and thrown away at the end of the loop. 'Sci-Fi' and 'Comedy' are assigned to $oval and $eval respectively and printed out.

      The second time around, $_ is assigned 'Action', $oval and $eval each cop an undef, and a mess gets printed out.

      So the first thing you want to do is:

      for my $oval( @categories ) { my $eval = shift @categories; printf ("%15s %15s\n", $oval, $eval ); }

      You might want to consider using each, but that would be somewhat obfuscated. That is left as an exercise for the reader.

      update: oops! I completely misread the code. That's a while, not a foreach you had. In which case it works fine. All I can say in my defense is that it's an unusual construct. Which may be a warning flag for maintainability.

      grinder wanders off to bed

      --
      g r i n d e r
      just another bofh