8

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

  1. first third is in left column
  2. middle third is in middle column
  3. and last third is in right column

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.

4

6 回答 6

8
use List::MoreUtils qw( part );
my $num_rows = int(@a/3);
my @aoa = map [ @a[@$_] ], part { $_ % $num_rows } 0..$#a;
print("@$_\n") for @aoa;

或者

use List::MoreUtils qw( part );
my $num_rows = int(@a/3);
my @aoa = part { $_ % $num_rows } 0..$#a;
print("@a[ @$_ ]\n") for @aoa;

或者

my $num_rows = int(@a/3);
for my $row_num (0..$num_rows-1) {
   print("@a[ map { $row_num + $num_rows*$_ } 0..2 ]\n");
}

以上不假定@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;

或者

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;

或者

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");
}
于 2013-10-17T03:31:42.343 回答
4

读完这个问题后,它看起来很像我在Perl6::Form的文档中读到的一个例子。(这是 Perl5 的实现)

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

如果任何字符串的长度超过分配给它的长度,它就不会像你想要的那样工作。

...
$array[-1] .= ' lllllll';
...
aaa      fff      kkk
bbb      ggg      lll
ccc      hhh      lllllll
ddd      iii
eee      jjj

当然,您可以在调用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 ^
于 2013-10-17T22:29:35.683 回答
3

这是我的解决方案,希望对你有所帮助。

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;
}
于 2013-10-17T02:27:54.680 回答
3
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";
}
于 2013-10-17T02:56:18.550 回答
2

另外的选择:

use strict;
use warnings;

my @a = qw(aaa bbb ccc ddd eee fff ggg hhh iii jjj kkk lll);
my @aoa;
push @{ $aoa[ $_ % 4 ] }, $a[$_] for 0 .. $#a;
print "@{ $_ }\n" for @aoa;
于 2013-10-17T04:48:23.723 回答
0

4 LOC:非常简单...享受

 my @tokens = qw(aaa bbb ccc ddd eee fff ggg hhh iii jjj kkk lll);
 my $text = join(" ",@tokens);
 while($text =~ /[^ ]+ [^ ]+ [^ ]+/g)
 {
     print "$&\n";
 }

萨米尔

于 2013-10-18T15:23:10.180 回答