Хотя модули предлагают более простое управление и функции, если вам нужно только распечатать их в виде сетки
use warnings;
use strict;
use feature 'say';
my @ary = ([1..3], [10..12], [100..102]);
foreach my $row (@ary) {
printf "%7.3f ", $_ for @$row;
say ''
}
Печать
1.000 2.000 3.000
10.000 11.000 12.000
100.000 101.000 102.000
Выберите ваш спецификатор (%7.3f
выше) в зависимости от того, какие данные у вас есть. Смотри sprintf
Если в первой строке есть заголовки, shift
выводится из массива и печатается с той же шириной, но с использованием %s
my @ary = ([qw(one two three)], [1..3], [10..12], [100..102]);
printf "%7s ", $_ for @{shift @ary};
say '';
foreach my $row (@ary) {
printf "%7.3f ", $_ for @$row;
say ''
}
Печатается так же, как указано выше, но с (выровненными) именами столбцов в первой строке.
Если « сетка данных » означает числовые данные, то код может обнаружить, существует ли строка заголовка, с разумным предположением, что первая строка содержит что-то нечисловое
use List::Util qw(any);
my $have_header = any { /[^0-9.+-]/ } @{$ary[0]};
, что также предполагает отсутствие NaN
и 1e02
или что-то подобное в первой строке.
Еще лучше, используйте looks_like_number
из Scalar :: Util
use List::Util qw(any);
use Scalar::Util qw(looks_like_number);
my $have_header = any { not looks_like_number($_) } @{$ary[0]};
Здесь используется внутренний смысл Perl того, что число равно , и, среди прочего, учитывается NaN
и экспоненциальная запись.
Если программе необходимо определить ширину столбцов или они сильно различаются, для приятного вывода есть еще что сделать, поскольку нам нужна максимальная ширина каждого столбца.
use warnings;
use strict;
use feature 'say';
use List::Util qw(max);
my $file = shift @ARGV || 'data.txt';
open my $fh, '<', $file or die "Can't open $file: $!";
my @ary = map { [ split ] } <$fh>;
my @maxw = (1) x @{$ary[0]};
for my $r (@ary) {
for (0..$#$r) {
my $len = length $r->[$_];
$maxw[$_] = $len if $len > $maxw[$_]
}
};
my $hdr = shift @ary;
printf "%$maxw[$_]s ", $hdr->[$_] for 0..$#$hdr;
say '';
for my $i (0..$#ary) {
printf "%$maxw[$_].2f ", $ary[$i]->[$_] for 0..$#{$ary[$i]};
say '';
}
Ожидаются цифры, кроме заголовка. Несколько других разумных предположений сделаны.
С входным data.txt
файлом, используемым для заполнения массива
one two three
1.12 1.1 12
1.00 10.00 102.000
программа печатает
one two three
1.12 1.10 12.00
1.00 10.00 102.00
Примечание. Если числа вычисляются в программе, эти скаляры используются в качестве чисел, и длина строки, представляющей их в печати, должна запрашиваться как length sprintf "%s", $num
. Когда они читаются из файла, они воспринимаются как строки, что для простоты используется выше.