Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

[Solved] Printing a 2D array into constant-sized columns

by mascip (Pilgrim)
on Apr 01, 2014 at 11:12 UTC ( [id://1080532]=perlquestion: print w/replies, xml ) Need Help??

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

Hi all, I want a display_2d() function:

my @accounts = [ [ current => 1000 ], [ savings => 2000 ], [ other => 500 ], ]; display_2d(\@accounts); # Should display: current | 1000 savings | 2000 other | 500
I just wrote this code:
my $width_col = 8; say join ' | ', map { # Give each column the same size length($_) >= $width_col ? $_ : $_ . " "x($width_col-length($_)) # add spaces } @$_ for @rows;
and that felt unnecessary. Is there no CPAN module to do this? I'm pretty sure I'm not the only one needing this function.

I found Array::Columnize but it only displays one dimensional arrays. And flattening my array does not do the trick: everything ends up displayed in the wrong order. My solution with Array::Columnize ended up being almost as long as my solution without it. And allows for less flexibility (columns of different width, for example)

And Array::PrintCols makes my terminal bug for a minute and then display nothing.

Have you come across dispay_2d() anywhere on CPAN?

Replies are listed 'Best First'.
Re: Printing a 2D array into constant-sized columns
by Happy-the-monk (Canon) on Apr 01, 2014 at 11:24 UTC

    There are builtins like sprintf and printf .

    Do they not bring the solution to your task?

    If they don't, the keywords to look for on CPAN would be "Format" or "Formatter", I think. Or did I misunderstand your task?

    Cheers, Sören

    Créateur des bugs mobiles - let loose once, run everywhere.
    (hooked on the Perl Programming language)

      Thank a lot! Using the keyword "format" I found Text::Column which does exactly what I need.

      I didn't know that printf could deal with arrays, that's good to know! I will learn how to use these at some point, but it feels like learning a new language, so I keep on delaying.

      Problem solved :-)

Re: [Solved] Printing a 2D array into constant-sized columns
by hazylife (Monk) on Apr 01, 2014 at 15:01 UTC
    Obviously printf/sprintf is the way to go, but there are other options:
    #!/usr/bin/perl use strict; my @accounts = ( [ current => 1000 ], [ savings => 2000 ], [ other => 500 ], ); write for @accounts; format STDOUT = @<<<<<<< | @<<<<<<< $_->[0], $_->[1] # EDIT: or just @$_ .
Re: [Solved] Printing a 2D array into constant-sized columns
by Laurent_R (Canon) on Apr 01, 2014 at 17:52 UTC
    Hi, just giving an example using printf:
    use strict; use warnings; my @accounts = [ [ current => 1000 ], [ savings => 2000 ], [ other => 500 ], ]; foreach my $sub_ref (@accounts) { printf "%-10s | %10d\n", $_->[0], $_->[1] for @$sub_ref; }
    Output:
    current | 1000 savings | 2000 other | 500
    Update: Seeing hazylife's EDIT in the code section, it came to my mind that my above code could also be simplified to:
    foreach my $sub_ref (@accounts) { printf "%-10s | %10d\n", @$_ for @$sub_ref; }
    Please also note that my code might look slightly more complex (nested loops) because it is working on the OP's original AoA structure, whereas other solutions presented so far were just working on simple arrays.

      Thank you :-) This seems to be enough is my case:

      printf "%-10s | %10d\n", @$_ for @rows;
      Unless if I missed something in your message (what is AoA?)

      I found this post as a printf tutorial, will read it this week: Using (s)printf().

      What I like about Text::Column is that the code is simple, clear, and anyone can understand it. But I've waited too long before learning printf, it's about time! Your post gave me the energy to get started, thanks a lot.

        An AoA is an array of arrays. But in fact your structure is more complicated, it is an array containing a reference to an array of arrays (so it is really an AoAoA). I can't be sure of what you intended to do, but I would guess that you really wanted this:
        my @accounts = ( [ current => 1000 ], [ savings => 2000 ], [ other => 500 ], );
        instead of this:
        my @accounts = [ [ current => 1000 ], [ savings => 2000 ], [ other => 500 ], ];
        The difference, if you don't see it, is in the round surrounding parens, versus square surrounding brackets. The first one (an AoA) looks like this:
        0 ARRAY(0x80359d38) 0 ARRAY(0x80355ce8) 0 'current' 1 1000 1 ARRAY(0x80359d50) 0 'savings' 1 2000 2 ARRAY(0x803fe470) 0 'other' 1 500
        and the second one is clearly more complicated, as it has one more level of nesting:
        0 ARRAY(0x80359d38) 0 ARRAY(0x80356108) 0 ARRAY(0x80360410) 0 'current' 1 1000 1 ARRAY(0x80359c18) 0 'savings' 1 2000 2 ARRAY(0x80359bd0) 0 'other' 1 500
        Ah, and yes, by all means, learn to use sprintf and printf, they are really useful as soon as you need to format output.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1080532]
Approved by Happy-the-monk
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others wandering the Monastery: (4)
As of 2024-04-25 05:29 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found