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

Hi monks

I have an array which can be filled with different number of elements. E.g.

my @array = ('sv-bbh-2','sv-bbh-3','sv-bbh-4', 'sv-bbh-5','dwdm02','avo00106','avo01000');

This array could have 1 element or 217 elements.

What I now want is to print it in the form of a table (without border) to a xterm window:

adsm-02 besy-02 c006603 c007581 c008433 c009684 asterix c003097 c006664 c007653 c008433-1 c009853 avo00106 c003701 c006790 c007760 c008434 c009992 avo01000 c003706 c006792 c007761 c008436 c009993

The column width should be variable.

It's the same output you get when you use "ls" without any parameters in an overcrowded directory.

Is there a special Perl function to do this?

Thank you very much, Kurt

Replies are listed 'Best First'.
Re: Create table from a list of values?
by halley (Prior) on Jul 28, 2003 at 16:26 UTC
    I think Text::Table is a good start. You "write" to the table one row at a time and it figures out the correct widths for you when you're done. I had actually written my own before finding this one. Mine is a bit smarter so maybe I'll submit it sometime, but I'm hesitant to add to an already crowded field.

    The Perl Cookbook also has a few examples that would help you when you have text layout issues that you figure someone else has solved before.

    --
    [ e d @ h a l l e y . c c ]

(jeffa) Re: Create table from a list of values?
by jeffa (Bishop) on Jul 28, 2003 at 16:38 UTC
    Text::Table is definitely the way to go ... but you still have to split up your one dimensional array into two in order to use it. I recently posted some code that does such (emulate Python's range function). Putting the two together yields:
    use strict; use warnings; use Text::Table; use Data::Dumper; my $step = shift || 5; my $tb = Text::Table->new(map "head$_", 1..$step); my @array = qw( adsm-02 besy-02 c006603 c007581 c008433 c009684 asterix c003097 c006664 c007653 c008433-1 c009853 avo00106 c003701 c006790 c007760 c008434 c009992 avo01000 c003706 c006792 c007761 c008436 c009993 ); my @two_d = map[ @array[$_..$_+$step-1] ], range(0,$#array,$step); $tb->load(@two_d); print $tb; sub range {grep!(($_-$_[0])%($_[2]||1)),$_[0]..$_[1]}
    Hope this helps. :)

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    
Re: Create table from a list of values?
by cianoz (Friar) on Jul 28, 2003 at 17:19 UTC
    i played a bit with it... (stupid ls replacement)
    #! /usr/bin/perl -w use strict; my $cols = $ENV{COLUMNS} || 80; ## you need to "export COLUMNS" for this to work.. my $dir = shift || '.'; opendir(DIR, $dir) || die "can't opendir $dir: $!"; my @words = grep { !/^\./ } readdir(DIR); closedir DIR; my $maxlength = 0; for(@words) { my $leng = length($_); $maxlength = $leng if($leng > $maxlength); } my $numcols = int($cols / $maxlength); my $rem = $cols % $maxlength; $numcols-- if($rem < $numcols); #at least 1 space between columns.. my $colwidth = int($cols / $numcols); for(my $i = 0; $i <= $#words; $i++) { printf("%-${colwidth}s", $words[$i]); print "\n" if((($i + 1) % $numcols) == 0); } print "\n";
Re: Create table from a list of values?
by bart (Canon) on Jul 28, 2003 at 16:42 UTC
    Just use tabs. :)
    { local($,, $\) = ("\t", "\n"); print @array; }
    Most likely, the tabs will do the right thing at the right border of the windows, i.e. wrap to the next line.

    If you don't like my use of special variables, you can use other means:

    print join("\t", @array) . "\n";

    It won't do you much good if you want to save the data in a text file, instead of just displaying it.

Re: Create table from a list of values?
by kutsu (Priest) on Jul 28, 2003 at 16:24 UTC

    Try format, it's chapter 11 in the Camel book

    Update: halley's way is better, but I'll leave this up as another way to do it

    "Pain is weakness leaving the body, I find myself in pain everyday" -me

      (In general, I don't recommend the format feature to newcomers to Perl. I think it's going away completely for perl6: there are so many other ways to get the same functionality without requiring first-class syntax hacks.)

      --
      [ e d @ h a l l e y . c c ]

Re: Create table from a list of values?
by cleverett (Friar) on Jul 28, 2003 at 16:46 UTC
    Search CPAN on the search terms "terminal width". Hint: you have to search past the first page for what you want.
Re: Create table from a list of values?
by cleverett (Friar) on Jul 28, 2003 at 17:42 UTC
    Heh, Text::Table works by the row, exclusively. But the guy wants "ls" style output, where the next item appears just beneath or at the top of the next column.

    Reading the docs, I can't see whereText::Table does the work of:

    1. figuring out how wide the terminal is
    2. calculating how many columns can fit
    3. breaking the data up into columns as needed

    By the time you've done all that, printing each row n by selecting the nth item from each column in sequence, padding items out as needed, and printing a newline is cake.