2

配列の内容を行に出力するプログラムがあります。各配列を隣り合わせの列に印刷したいと思います。

これはコードです:

#!/usr/local/bin/perl

use strict;
use warnings;

my @M_array;
my @F_array;

open (my $input, "<", 'ssbn1898.txt');

while ( <$input> ) {

    chomp;

    my ( $name, $id ) = split ( /,/ ); 

    if ( $id eq "M" ) {
        push ( @M_array, $name );
    }
    else {
        push ( @F_array, $name ); 
    }
}
close ( $input );

print "M: @M_array \n"; 
print "F: @F_array \n";

これは可能ですか、それともできないことをしようとしていますか?

希望のフォーマット:

M      F 
Namem1 Namef1 
Namem2 Namef2 
4

6 に答える 6

3

関数を使用して、データ間に任意のセパレーターを追加できます。join以下の例では、タブで区切られた配列内のデータをフォーマットします。

...
use List::MoreUtils qw/pairwise/;

my $separator = "\t";
print join($separator, qw(M F)), "\n";
print join(
   "\n", 
   pairwise { ( $a // '') . $separator . ( $b // '') } @M_array, @F_array
), "\n";
...
于 2015-07-13T13:51:09.267 に答える
2

Perl 形式を使用する必要があると思います。Perl のドキュメントを参照してください。@*あなたのケースではフォーマットフィールドを使用したいかもしれません。

最後に目的の出力を印刷するためにコードを拡張しました

use strict;
use warnings;

my @M_array;
my @F_array;

open (my $input, "<", 'ssbn1898.txt');

while ( <$input> ) {

    chomp;

    my ( $name, $id ) = split ( /,/ ); 

    if ( $id eq "M" ) {
        push ( @M_array, $name );
    }
    else {
        push ( @F_array, $name ); 
    }
}
close ( $input );

unshift @M_array, 'M';
unshift @F_array, 'F';

my $namem; 
my $namef;

my $max = 0;

$max = (length($_) gt $max  ? length($_) : $max) for @M_array;
my $w = '@' . '<' x $max;

eval "
format STDOUT = 
$w @*
\$namem, \$namef 
.
";

while ( @M_array or @F_array) {

    $namem = shift @M_array || '';
    $namef = shift @F_array || '';

    write;

}
于 2015-07-13T14:29:28.553 に答える
1

joinおそらく最も簡単な方法はtabs、列をうまく整列させることです。

join ( "\t", @array ),

別の方法として、perl は(s)printfによるフォーマットを許可します:

printf ( "%-10s %-10s", "first", "second" );

または、より詳細な「フォーマット」

あなたがやろうとしていることを考えると、2つの配列を列に入れることです:

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

my $format = "%-10s\t%-10s\n";

my @M_array = qw ( M1 M2 M3 M4 M5 );
my @F_array = qw ( F1 F2 F3 );
my $maxrows = $#M_array > $#F_array ?  $#M_array : $#F_array; 

printf ( $format, "M", "F" );
for my $rownum ( 0..$maxrows ) { 
    printf ( $format, $M_array[$rownum] // '', $F_array[$rownum] // '' );

}

これにより、ヘッダー行が出力され、一度に 1 行ずつ出力される配列がループされます。//何かが定義されているかどうかをテストする条件付き操作です。ただし、新しい perl でのみ使用できます*。古いバージョンで||はうまくいきます -ほとんど同じですが、ハンドル''0わずかに異なります。

* Perl 5.10 以降、かなり安全ですが、一部のシステムはまだ perl 5.8 で動き回っているため、言及する価値があります。

于 2015-07-13T14:30:11.730 に答える
1

@HunterMcMillen からの借用

use strict;
use warnings;
use feature "say";

local $, = "\t";   # separator when printing list

my $i = (@F_array > @M_array) ? $#F_array : $#M_array;

say qw(M F);
say $M_array[$i] //"", $F_array[$i] //"" for 0 .. $i;
于 2015-07-13T14:57:57.250 に答える
1

sprintf関数を使用して出力をフォーマットすることもできますが、解決すべき問題がいくつかあります。配列のエントリ数が同じでない場合はどうなるでしょうか。このためには、プレースホルダーが必要です。列に収まる必要がある文字数は? どのように揃えるべきですか?説明のためのいくつかのコード:

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

my @m = (1, 2, 3);
my @f = (11, 22, 33, 44);

# calculate how many rows to display
my $max = @m;
if (@m < @f) {
    $max = @f;
}

# placeholder for missing data
my $none = '-';

# formatting 20 chars per column, left aligned
my $fmt = "%-20s%-20s\n";

# print header
print sprintf($fmt, "M", "F");

# print data rows
foreach my $i (0..$max-1) {
    print sprintf($fmt, ($m[$i] or $none), ($f[$i] or $none));
}

より洗練された書式設定 (中央揃えのテキストなど) に関心がある場合は、レポート生成用に Perl が提供する特別な書式設定機能に切り替える必要があります。

于 2015-07-13T14:31:21.680 に答える
0

Text::Table は perl ディストリビューションに付属する必須モジュールだと思います (インストールする必要があるだけです)。以下のドキュメントを参照してください -

Text::Table のドキュメント

コンテンツを配列として add() メソッドに渡す必要があります。

于 2015-07-15T03:49:46.887 に答える