I have a sorted array in a perl script eg:
qw(aaa bbb ccc ddd eee fff ggg hhh iii jjj kkk lll)
Is there an easy way to display it in three columns so that
This is so the elements can be displayed running down the screen instead of across it. eg
aaa eee iii
bbb fff jjj
ccc ggg kkk
ddd hhh lll
I have been trying to use modulus but it's getting complicated and thought there might be an elegant solution. Ultimately I intend to use it for something similar to select
in bash.
Thank you.
use List::MoreUtils qw( part );
my $num_rows = int(@a/3);
my @aoa = map [ @a[@$_] ], part { $_ % $num_rows } 0..$#a;
print("@$_\n") for @aoa;
or
use List::MoreUtils qw( part );
my $num_rows = int(@a/3);
my @aoa = part { $_ % $num_rows } 0..$#a;
print("@a[ @$_ ]\n") for @aoa;
or
my $num_rows = int(@a/3);
for my $row_num (0..$num_rows-1) {
print("@a[ map { $row_num + $num_rows*$_ } 0..2 ]\n");
}
Versions of the above that don't assumes @a % 3 == 0.
use List::MoreUtils qw( part );
use POSIX qw( ceil );
my $num_rows = ceil(@a/3);
my @aoa = map [ @a[@$_] ], part { $_ % $num_rows } 0..$#a;
print("@$_\n") for @aoa;
or
use List::MoreUtils qw( part );
use POSIX qw( ceil );
my $num_rows = ceil(@a/3);
my @aoa = part { $_ % $num_rows } 0..$#a;
print("@a[ @$_ ]\n") for @aoa;
or
use POSIX qw( ceil );
my $num_rows = ceil(@a/3);
for my $row_num (0..$num_rows-1) {
print("@a[ grep { $_ < @a } map { $row_num + $num_rows*$_ } 0..2 ]\n");
}
After reading this question, it looked a lot like an example that I read in the docs for Perl6::Form. ( Which is the Perl5 implementation )
use strict;
use warnings;
use Perl6::Form;
my @array = qw'aaa bbb ccc ddd eee fff ggg hhh iii jjj kkk lll';
print form
"{[[[[[:} {:[[[[:} {:[[[[[}",
\@array, \@array, \@array;
aaa eee iii
bbb fff jjj
ccc ggg kkk
ddd hhh lll
It won't work like you want it to, if any of the strings is longer than has been allotted for it.
...
$array[-1] .= ' lllllll';
...
aaa fff kkk
bbb ggg lll
ccc hhh lllllll
ddd iii
eee jjj
Of course you could calculate the required width before the call to form.
...
use List::Util qw'max';
my $max_length = max 5, map length, @array; # at least 5
my $TERMINAL_WIDTH = 80;
my $number_of_cols = int( $TERMINAL_WIDTH / ($max_length+1) );
my $single = '{:' . ( '[' x ($max_length-4) ) . ':} ';
print $single, "\n\n"; # debug statement
print form
$single x $number_of_cols,
(\@array) x $number_of_cols;
{:[[[[[[[:}
aaa ccc eee ggg iii kkk
bbb ddd fff hhh jjj lll lllllll
80 ^
Here is my solution, hope it helps you.
use strict;
use warnings;
my @arr = ("aaa", "bbb", "ccc", "ddd", "eee", "fff", "ggg", "hhh", "iii", "jjj", "kkk", "lll");
my $size = @arr;
my $column = 3;
my $mod = $size / $column;
my $i = $size;
my $count = 0;
while ($i > 0) {
my $k = $count;
while ($k < $size) {
print "$arr[$k]\t";
$k += $mod;
}
print "\n";
$count++;
$i -= $column;
}
my @foo = qw(aaa bbb ccc ddd eee fff ggg hhh iii jjj kkk lll);
my $rows = int( (@foo+2) / 3 );
my @row;
$row[$_ % $rows][$_ / $rows] = $foo[$_] for 0..$#foo;
for my $row (@row) {
print join(' ', @$row), "\n";
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With