Formatting a single line without effecting the entire table with the Text::Table module

Discussion in 'Perl Misc' started by Mothra, Mar 10, 2005.

  1. Mothra

    Mothra Guest

    Hi All,

    I have a data structure (see script) that I need to printout. I almost have
    what I
    need but I cannot figure out how to format just one line (center it )
    sample output is:
    kreimer
    EMMI CHRISTIAN 0 0 17
    TRACEY LUSBY 0 4 0
    TONA MCGEAN 0 7 0
    Total: 0 11 17

    What I would like is the word "kreimer" centered and the other names
    remain left justified. What am I doing wrong?

    Thanks

    Lynn




    ----------script--------------
    use strict;
    use warnings;
    use Text::Table;
    use diagnostics;
    use Data::Dumper;

    my $people = {
    'kreimer' => {
    'TRACEY LUSBY' => [ 0, 4, 0 ],
    'EMMI CHRISTIAN' => [ 0, 0, 17 ],
    'TONA MCGEAN' => [ 0, 7, 0 ],

    },
    'OTHER' => {
    'STEPHEN ESPESET' => [ undef, 4, 27 ],
    'PATRICK HOONHOU' => [ 1, 3, 4 ],
    'WOODROW WILSON' => [ undef, 2, 1 ],

    },
    'lusby' => {
    'KEVIN FLUETSCH' => [ 0, 0, 22 ],
    'DOUG BOSWORTH' => [ 0, 1, 6 ],
    'DOUG PENICK' => [ 1, 2, 22 ],

    },

    };

    foreach my $tmp_people( values %{ $people->{'OTHER'} } ) {

    if ( !defined( $tmp_people->[0] ) ) { $tmp_people->[0] = 0 }
    if ( !defined( $tmp_people->[1] ) ) { $tmp_people->[1] = 0 }
    if ( !defined( $tmp_people->[2] ) ) { $tmp_people->[2] = 0 }
    }

    my %manager_total = ();
    foreach my $managers( keys %{$people} ) {
    foreach my $person( keys %{ $people->{$managers} } ) {
    $manager_total{$managers}[0] += $people->{$managers}->{$person}[0];
    $manager_total{$managers}[1] += $people->{$managers}->{$person}[1];
    $manager_total{$managers}[2] += $people->{$managers}->{$person}[2];
    }
    }

    my $tb = Text::Table->new(

    {
    title => 'Name',
    align => 'left',
    align_title => 'center'
    },

    {
    title => 'Last Month',
    align => 'center',
    align_title => 'center'
    },

    {
    title => 'YTD',
    align => 'center',
    align_title => 'center'
    },

    {
    title => 'Rolling 12 months',
    align => 'center',
    align_title => 'center'
    },

    );

    #print Dumper (\%manager_total);

    foreach my $managers( keys %{$people} ) {
    $tb->add($managers);

    foreach my $person( sort Mysort keys %{ $people->{$managers} } ) {

    $tb->add( "$person", @{ $people->{$managers}->{$person} } );


    }
    $tb->add( "Total: ", @{ $manager_total{$managers} } );
    $tb->add();
    }

    print $tb;

    sub Mysort {

    my ( undef, $first ) = split ( / /, $a );
    my ( undef, $last ) = split ( / /, $b );
    $first cmp $last;

    }
     
    Mothra, Mar 10, 2005
    #1
    1. Advertising

  2. Mothra <> wrote:

    > if ( !defined( $tmp_people->[0] ) ) { $tmp_people->[0] = 0 }



    Excessive punctuation is bad for your (mental) health:

    $tmp_people->[0] = 0 unless defined $tmp_people->[0];


    > if ( !defined( $tmp_people->[1] ) ) { $tmp_people->[1] = 0 }
    > if ( !defined( $tmp_people->[2] ) ) { $tmp_people->[2] = 0 }



    Gak! There are only 2 characters that are different between all
    three of those lines, that indicates that it can be written better.

    foreach ( 0 .. 2 ) {
    $tmp_people->[$_] = 0 unless defined $tmp_people->[$_];
    }

    but that won't scale when you add a 4th tmp_people, so maybe:

    foreach ( 0 .. $#{ $tmp_people } ) {
    $tmp_people->[$_] = 0 unless defined $tmp_people->[$_];
    }

    but since foreach uses an alias, we can make it even simpler
    by not doing the indexing ourselves, let perl do the indexing:

    $_ = defined() ? $_ : 0 for @$tmp_people; # untested

    or

    for ( @$tmp_people ) {
    $_ = defined() ? $_ : 0;
    }

    or

    for ( @$tmp_people ) { # this would be my choice of replacement code
    $_ = 0 unless defined;
    }


    > $manager_total{$managers}[0] += $people->{$managers}->{$person}[0];
    > $manager_total{$managers}[1] += $people->{$managers}->{$person}[1];
    > $manager_total{$managers}[2] += $people->{$managers}->{$person}[2];



    When you see repeated patterns in code like that, it usually
    means you can easily come up with a better design that doesn't
    repeat so much.


    --
    Tad McClellan SGML consulting
    Perl programming
    Fort Worth, Texas
     
    Tad McClellan, Mar 10, 2005
    #2
    1. Advertising

  3. * Mothra wrote:
    >
    > I have a data structure (see script) that I need to printout. I almost
    > have what I need but I cannot figure out how to format just one line
    > (center it ) sample output is:
    >
    > kreimer
    > EMMI CHRISTIAN 0 0 17
    > TRACEY LUSBY 0 4 0
    > TONA MCGEAN 0 7 0
    > Total: 0 11 17
    >
    > What I would like is the word "kreimer" centered and the other names
    > remain left justified. What am I doing wrong?


    After reading this module's documentation i'm thinking there's no way to
    format a few lines differently than others. Consider to use another
    format to indicate such "captions". Perhaps something like indentions:

    kreimer
    EMMI CHRISTIAN 0 0 17
    TRACEY LUSBY 0 4 0
    TONA MCGEAN 0 7 0
    Total: 0 11 17

    >
    > ----------script--------------
    >
    > foreach my $tmp_people( values %{ $people->{'OTHER'} } ) {
    > if ( !defined( $tmp_people->[0] ) ) { $tmp_people->[0] = 0 }
    > if ( !defined( $tmp_people->[1] ) ) { $tmp_people->[1] = 0 }
    > if ( !defined( $tmp_people->[2] ) ) { $tmp_people->[2] = 0 }
    > }


    Since youre values are always numbers, this loop can be reduced to:

    for ( values %{$people->{OTHER}} ) {
    $_ ||= 0 for @$_;
    }

    For testing for definedness, I've heard about an »//=« operator that
    will be introduced in Perl6, but here this should be sufficient.

    >
    > my %manager_total = ();
    > foreach my $managers( keys %{$people} ) {
    > foreach my $person( keys %{ $people->{$managers} } ) {
    > $manager_total{$managers}[0] += $people->{$managers}->{$person}[0];
    > $manager_total{$managers}[1] += $people->{$managers}->{$person}[1];
    > $manager_total{$managers}[2] += $people->{$managers}->{$person}[2];
    > }
    > }


    For me, your style isn't as good as it could be. Try out:

    my %manager_total = ();
    for my $m ( keys %{$people} ) {
    for my $p ( values %{$people->{$m}} ) {
    for my $i ( 0 .. $#{$p} ) {
    $manager_total{ $m }[ $i ] += $p->[$i];
    }
    }
    }

    [...]

    >
    > foreach my $managers( keys %{$people} ) {
    > $tb->add($managers);
    >
    > foreach my $person( sort Mysort keys %{ $people->{$managers} } ) {
    >
    > $tb->add( "$person", @{ $people->{$managers}->{$person} } );

    ^^^

    Adding here two blanks will indenting these lines (see above).

    >
    >
    > }
    > $tb->add( "Total: ", @{ $manager_total{$managers} } );
    > $tb->add();


    On my system, adding *nothing* will produce the warning "Use of
    uninitialized value in range (or flop) at Text/Table.pm line 380".
    Perhaps you want to add a blank to generate a blank line

    $tb->add( " " );

    > }
    >
    > print $tb;
    >
    > sub Mysort {
    >
    > my ( undef, $first ) = split ( / /, $a );
    > my ( undef, $last ) = split ( / /, $b );
    > $first cmp $last;
    >
    > }


    I'd write this as

    sub Mysort {
    (split / /, $a)[1] cmp (split / /, $b)[1]
    }

    but I don't think every proposal above results in better readability.
    This might depending on one's individual flair.

    regards,
    fabian
     
    Fabian Pilkowski, Mar 11, 2005
    #3
  4. Mothra

    Anno Siegel Guest

    Mothra <> wrote in comp.lang.perl.misc:
    > Hi All,
    >
    > I have a data structure (see script) that I need to printout. I almost have
    > what I
    > need but I cannot figure out how to format just one line (center it )
    > sample output is:
    > kreimer
    > EMMI CHRISTIAN 0 0 17
    > TRACEY LUSBY 0 4 0
    > TONA MCGEAN 0 7 0
    > Total: 0 11 17
    >
    > What I would like is the word "kreimer" centered and the other names
    > remain left justified. What am I doing wrong?


    [code appreciated, but snipped]

    Text::Table currently only supports one alignment specification for
    each column, so there is no way you can require central alignment for
    some lines and not for others. You are not the first one who wants
    to do that, so a future revision may support it, but that's not coming
    soon.

    For the moment, if you can do with a fixed amount of indentation instead
    of true center alignment, just prefix the (manager-) names with a number
    of blanks when you add them (see below).

    foreach my $managers( keys %{$people} ) {
    $tb->add( " $managers");

    Oh, and to add a blank line to the table, add a single empty string,
    not an empty list:

    $tb->add( '');

    If you must have center alignment, you can probably use the ->colrange
    method to print the centered names manually. That should be doable,
    though I'm not quite sure how I would do it. Ask again if you need it.

    Anno
     
    Anno Siegel, Mar 11, 2005
    #4
  5. Mothra

    Anno Siegel Guest

    Fabian Pilkowski <-marburg.de> wrote in comp.lang.perl.misc:

    [Text::Table]

    > On my system, adding *nothing* will produce the warning "Use of
    > uninitialized value in range (or flop) at Text/Table.pm line 380".


    Oh... that's a bug. The next release will silently ignore empty lines.
    I can't believe I don't have a test for this. Thanks for the input.

    > Perhaps you want to add a blank to generate a blank line
    >
    > $tb->add( " " );
    >
    > > }


    An empty string will do. Even "undef" is accepted (though not recommended)
    for the purpose.

    Anno (author of Text::Table)
     
    Anno Siegel, Mar 11, 2005
    #5
  6. Mothra

    lynn Guest

    Hi Tad,

    "Tad McClellan" <> wrote in message
    news:...
    > Lynn <> wrote:
    >
    > Excessive punctuation is bad for your (mental) health:

    (snipped)
    >
    > Gak! There are only 2 characters that are different between all
    > three of those lines, that indicates that it can be written better.
    >

    (more snippage)
    > but since foreach uses an alias, we can make it even simpler
    > by not doing the indexing ourselves, let perl do the indexing:
    >
    > $_ = defined() ? $_ : 0 for @$tmp_people; # untested
    >
    > or
    >
    > for ( @$tmp_people ) {
    > $_ = defined() ? $_ : 0;
    > }

    (even more snippage)
    > When you see repeated patterns in code like that, it usually
    > means you can easily come up with a better design that doesn't
    > repeat so much.

    Thanks for your reply, That is great!! I like what you did to the code :)
    BTY, Where is the ? and : documented in perldoc? I can't find them
    (this is the reason I use diagnostics in my programs, it tells me what
    to type into perldoc)
    I tried:
    perldoc -f :
    No documentation for perl function `:' found
    perldoc -f ?
    No documentation for perl function `?' found
    perldoc ?
    No documentation found for "?".
    perldoc :
    No documentation found for ":".


    Thanks

    Lynn
     
    lynn, Mar 11, 2005
    #6
  7. Mothra

    Paul Lalli Guest

    "lynn" <> wrote in message
    news:4231a0a4$...
    > BTY, Where is the ? and : documented in perldoc? I can't find them
    > (this is the reason I use diagnostics in my programs, it tells me what
    > to type into perldoc)
    > I tried:
    > perldoc -f :
    > No documentation for perl function `:' found
    > perldoc -f ?
    > No documentation for perl function `?' found


    perldoc -f is for function names. Neither ? nor : are functions

    > perldoc ?
    > No documentation found for "?".
    > perldoc :
    > No documentation found for ":".


    perldoc <topic> for both the predefined documentation that comes with
    perl (see perldoc perltoc for a full list) as well as modules. ? and :
    are neither.

    Indeed, in the code your referenced, ? and : are not separate entities,
    but are instead a single operator, ?:

    This operator, like all operators, is documented in perldoc perlop. It
    is referred to therein as the "conditional operator", but you may also
    hear the term "trinary operator" (simply because it takes three
    arguments.

    Hope this helps,
    Paul Lalli
     
    Paul Lalli, Mar 11, 2005
    #7
  8. Mothra

    lynn Guest

    Hi Fabian,

    "Fabian Pilkowski" <-marburg.de> wrote in message
    news:...
    (snipped)

    > After reading this module's documentation i'm thinking there's no way to
    > format a few lines differently than others. Consider to use another
    > format to indicate such "captions". Perhaps something like indentions:


    After reading the other replys this is what I will do
    >
    > ----------script--------------
    >

    (snipped)

    > Since youre values are always numbers, this loop can be reduced to:


    > for ( values %{$people->{OTHER}} ) {
    > $_ ||= 0 for @$_;
    > }

    That looks good :)

    > For testing for definedness, I've heard about an »//=« operator that
    > will be introduced in Perl6, but here this should be sufficient.
    >

    (more snippage)

    > For me, your style isn't as good as it could be. Try out:


    > my %manager_total = ();
    > for my $m ( keys %{$people} ) {
    > for my $p ( values %{$people->{$m}} ) {
    > for my $i ( 0 .. $#{$p} ) {
    > $manager_total{ $m }[ $i ] += $p->[$i];
    > }
    > }
    > }

    Much better :)

    >
    > foreach my $managers( keys %{$people} ) {
    > $tb->add($managers);
    >
    > foreach my $person( sort Mysort keys %{ $people->{$managers} } ) {
    >
    > $tb->add( "$person", @{ $people->{$managers}->{$person} } );

    ^^^
    >> $tb->add();


    > On my system, adding *nothing* will produce the warning "Use of
    > uninitialized value in range (or flop) at Text/Table.pm line 380".
    > Perhaps you want to add a blank to generate a blank line


    I did not get any warnings, I am running perl 5.8.3 on windows.
    (I did use warnings!! )
    >
    > print $tb;
    >
    > sub Mysort {
    >
    > my ( undef, $first ) = split ( / /, $a );
    > my ( undef, $last ) = split ( / /, $b );
    > $first cmp $last;
    >
    > }


    > I'd write this as


    > sub Mysort {
    > (split / /, $a)[1] cmp (split / /, $b)[1]
    > }


    Looks good, Thanks for your response :)


    Lynn
     
    lynn, Mar 11, 2005
    #8
  9. Mothra

    lynn Guest

    Hi Anno
    "Anno Siegel" <-berlin.de> wrote in message
    news:d0rsmb$na6$-Berlin.DE...
    (snipped)
    >
    > [code appreciated, but snipped]
    >
    > Text::Table currently only supports one alignment specification for
    > each column, so there is no way you can require central alignment for
    > some lines and not for others. You are not the first one who wants
    > to do that, so a future revision may support it, but that's not coming
    > soon.


    First off I would like to say I really like your module :) It makes
    creating
    reports much easier.

    >
    > For the moment, if you can do with a fixed amount of indentation instead
    > of true center alignment, just prefix the (manager-) names with a number
    > of blanks when you add them (see below).
    >
    > foreach my $managers( keys %{$people} ) {
    > $tb->add( " $managers");


    This is what I have decided to do, Thanks!!

    >
    > Oh, and to add a blank line to the table, add a single empty string,
    > not an empty list:
    >
    > $tb->add( '');
    >

    Yes, I saw the reply from Fabian however, I did not receive the warnings
    he was refering to (odd). Thanks for all of your help!!

    Lynn
     
    lynn, Mar 11, 2005
    #9
  10. Mothra

    lynn Guest

    Hi Paul,

    "Paul Lalli" <> wrote in message
    news:4phYd.96063$g16.95797@trndny08...
    > "lynn" <> wrote in message
    > news:4231a0a4$...

    (snipped)
    >
    > perldoc <topic> for both the predefined documentation that comes with
    > perl (see perldoc perltoc for a full list) as well as modules. ? and :
    > are neither.


    Great ! now I can see the full list :)

    >
    > Indeed, in the code your referenced, ? and : are not separate entities,
    > but are instead a single operator, ?:
    >
    > This operator, like all operators, is documented in perldoc perlop. It
    > is referred to therein as the "conditional operator", but you may also
    > hear the term "trinary operator" (simply because it takes three
    > arguments.
    >
    > Hope this helps,

    Yes!! indeed this does help. Perl is a great programming language
    however, finding things in the documentation has caused me so much
    grief. I don't blame the doc though more on my ability to use them (perldoc)

    Once again, Thanks for all of your help :)

    Lynn
     
    lynn, Mar 11, 2005
    #10
  11. Mothra

    Anno Siegel Guest

    lynn <> wrote in comp.lang.perl.misc:

    [Text::Table]

    > Yes, I saw the reply from Fabian however, I did not receive the warnings
    > he was refering to (odd). Thanks for all of your help!!


    The bug is only in 1.107. You probably have an earlier version.

    Anno
     
    Anno Siegel, Mar 11, 2005
    #11
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Chumley the Walrus

    Style tag not effecting links in paging from datagrid

    Chumley the Walrus, Aug 4, 2004, in forum: ASP .Net
    Replies:
    0
    Views:
    360
    Chumley the Walrus
    Aug 4, 2004
  2. Psych971
    Replies:
    5
    Views:
    4,626
    bruce barker
    Dec 17, 2004
  3. =?Utf-8?B?TWFya0F1cml0?=

    GRIDVIEW: Effecting buttonfields on single gridview rows

    =?Utf-8?B?TWFya0F1cml0?=, May 23, 2006, in forum: ASP .Net
    Replies:
    0
    Views:
    484
    =?Utf-8?B?TWFya0F1cml0?=
    May 23, 2006
  4. Replies:
    4
    Views:
    396
    Jack Klein
    Jul 2, 2006
  5. David Southwell
    Replies:
    3
    Views:
    154
    Phrogz
    Nov 4, 2009
Loading...

Share This Page