Есть ли модуль, который дает мне вывод двух столбцов (или больше) на STDOUT? - PullRequest
2 голосов
/ 02 февраля 2010

есть ли модуль, который дает мне вывод двух столбцов (или больше) на STDOUT?

#!/usr/bin/env perl
use warnings;
use strict;

printf "%0.3d\n", $_ for 1 .. 100; 

Я хотел бы иметь 1-50 в первом столбце и 51-100 во втором.

Ответы [ 7 ]

4 голосов
/ 02 февраля 2010

Text :: Column

use Text::Column qw(format_array_table);

print format_array_table([map [$_, 50+$_], 1..50], [6, 6], [qw(first second)]);

Или, если вы работаете в системе UNIX, проложите через pr (1) .

open COLUMN, '|-', qw(pr -T2);
print COLUMN "$_\n" for 1..100;
4 голосов
/ 02 февраля 2010

Для этого вы можете использовать форматирование Perl.

Здесь - ссылка с учебником.

Вот фрагмент этой страницы:

format MYFILE = 
Name: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<        Salary: @###########.##
      $name,                                       $salary
.

Производит вывод:

Name: John Smith                           Salary:        78293.22

Символы форматирования имеют следующие характеристики форматирования:

>   right justified
#   right justified (numeric only; can include a decimal point) 
<   left justified 
|   center justified
*   left justified, fill in all data from value


Edit:

Вот более прямой ответ на ваш вопрос:

#!/usr/bin/perl

use strict;

my @data = (1..100);
my ($v1, $v2);

# Create formats
format ONECOL = 
Col1: @###
      $v1
.
format TWOCOL = 
Col1: @###        Col2: @###
      $v1,        $v2
.

# Set the two column format
$~ = "TWOCOL";

my $i = 0;
my $middle = int(@data/2) + (@data % 2);
for (my $x = $middle; $x < @data; $i++, $x++)
{
    $v1 = $data[$i];
    $v2 = $data[$x];
    write;
}

# Set the format to one column
if ($i < $middle)
{
    $~ = "ONECOL";
    $v1 = $data[$i];
    write;    
}
4 голосов
/ 02 февраля 2010

Может быть модуль для такого рода вещей ... или вы можете свернуть свой собственный:

use strict;
use warnings;

my $n_cols = shift @ARGV;
my @list = (1..100);
my $part_size = @list / $n_cols;
$part_size = int($part_size + 1) unless $part_size == int($part_size);
my $fmt = '%8s' x $n_cols . "\n";

for my $i (0 .. $part_size - 1){
    my @vals = map { defined($list[$_]) ? $list[$_] : '' }
               map { $_ * $part_size + $i }
               0 .. $n_cols;
    printf $fmt, @vals;

}
2 голосов
/ 02 февраля 2010

Посмотрите на Perl6::Form

use Perl6::Form;

my $col1 = [ 1..50 ];
my $col2 = [ 51..100 ];

print form '{[} {[}', $col1, $col2;


Таким образом, вы можете создать вспомогательную подпрограмму для получения правильного form, который может выглядеть примерно так:

sub mk_form {
    my $rows = shift;
    my @form;

    # calculate columns needed 
    use integer;
    my $cols = scalar @_ / $rows;
    $cols++ if scalar @_ % $rows;

    # create Perl6::Form args
    push @form, '{[} ' x $cols;
    push @form, [ splice @_, 0, $rows ] for 1..$cols;

    return @form;
}

Затем, чтобы создать колонную страницу в 50 строк:

say form mk_form(50, 1..101);

/ I3az /

PS: см. Вопрос SO Какие другие языки имеют функции и / или библиотеки, подобные формату Perl? , чтобы узнать больше о Perl6::Form.

2 голосов
/ 02 февраля 2010

Это попрошайничество для итераторов (нет! Но это весело). Обратите внимание, что пересмотренное решение также позволяет настроить количество столбцов.

#!/usr/bin/perl

use strict;
use warnings;

use List::AllUtils qw( min );

print_cols('%04d', 1, 100, 11);

sub print_cols {
    my ($fmt, $min, $max, $cols) = @_;
    my $its = partition($min, $max, $cols);

    while ( (my @vals = grep { defined } map {$_->()} @$its)) {
        printf join(' ', ($fmt) x @vals) . "\n", @vals;
    }

    return;
}

sub make_asc_it {
    my ($min, $max) = @_;
    return sub {
        return unless $min <= $max;
        return $min ++;
    }
}

sub partition {
    my ($min, $max, $cols) = @_;
    return unless $min <= $max;

    my $rows = sprintf '%.0f', ($max - $min) / $cols;
    my @its;

    for my $col (1 .. $cols) {
        push @its, make_asc_it(
            min( $min, $max ),
            min( $min + $rows - 1, $max )
        );
        $min += $rows;
    }
    push @its, make_asc_it($min, $max) if $min <= $max;

    return \@its;
}

Вывод для одиннадцати столбцов:

0001 0010 0019 0028 0037 0046 0055 0064 0073 0082 0091 0100
0002 0011 0020 0029 0038 0047 0056 0065 0074 0083 0092
0003 0012 0021 0030 0039 0048 0057 0066 0075 0084 0093
0004 0013 0022 0031 0040 0049 0058 0067 0076 0085 0094
0005 0014 0023 0032 0041 0050 0059 0068 0077 0086 0095
0006 0015 0024 0033 0042 0051 0060 0069 0078 0087 0096
0007 0016 0025 0034 0043 0052 0061 0070 0079 0088 0097
0008 0017 0026 0035 0044 0053 0062 0071 0080 0089 0098
0009 0018 0027 0036 0045 0054 0063 0072 0081 0090 0099
1 голос
/ 02 февраля 2010

Посмотрите на утилиту column . Я не думаю, что вы можете запросить определенное количество столбцов.

1 голос
/ 02 февраля 2010

Можете ли вы сделать это таким образом?

for ($count = 1; $count <=100; $count++) {
    printf "%d %d\n", $count, $count+50;
}
...