在Perl循环中需要帮助

时间:2014-09-22 18:23:58

标签: perl

我有一个包含以下数据的文件。我想打印一个外部文件,每9行总和。这是我的数据。

file.xyz

-0.485718003092488 3.25568455554021 -0.60544991716881 
-1.01253068155602 -2.49251542491767 0.713923699625837
0.791137982988487 -2.56492609246597 -0.853251541212567
-0.485718003092488 3.25568455554021 -0.60544991716881
-1.01253068155602 -2.49251542491767 0.713923699625837
0.791137982988487 -2.56492609246597 -0.853251541212567
-0.485718003092488 3.25568455554021 -0.60544991716881
-1.01253068155602 -2.49251542491767 0.713923699625837
0.791137982988487 -2.56492609246597 -0.853251541212567
-0.485718003092488 3.25568455554021 -0.60544991716881
-1.01253068155602 -2.49251542491767 0.713923699625837
0.791137982988487 -2.56492609246597 -0.853251541212567
-0.485718003092488 3.25568455554021 -0.60544991716881
-1.01253068155602 -2.49251542491767 0.713923699625837
0.791137982988487 -2.56492609246597 -0.853251541212567
-0.485718003092488 3.25568455554021 -0.60544991716881
-1.01253068155602 -2.49251542491767 0.713923699625837
0.791137982988487 -2.56492609246597 -0.853251541212567

我的输出看起来像

-2.121332105    -5.405270886    -2.234333276    6.221675693
-2.121332105    -5.405270886    -2.234333276    6.221675693

第一行是1-9的总和,第二行是10-18的总和。这里前9行和后9行的数据相同,它给出相同的值。我想用千行文件打印每个NINE大行文件的总和。

这是我的代码,它计算总和,但我需要分成两部分,如上所述。

感谢您的帮助和赞赏。

my @sums;
open FILE, "file.xyz" or die "Can't find";

while( <FILE> ) { # there is FILE written within angular brackets
    my @summands = split / /;
    foreach my $i ( 0 .. $#summands ) {
        $sums[$i] += $summands[$i];
    }
}
$total = sqrt($sums[0]*$sums[0]+$sums[1]*$sums[1]+$sums[2]*$sums[2]);
print "$sums[0], $sums[1], $sums[2], $total\n";

4 个答案:

答案 0 :(得分:2)

如下所示:

use strict;
use warnings;
use autodie;
open my $fh, '<', 'file.xyz';

my @sums;
my $n = 0;
while (<$fh>) {
    my @summands = split /\s+/;
    foreach my $i ( 0 .. $#summands ) {
        $sums[$i] += $summands[$i];
    }
    unless ( ++$n % 9 ) {
        my $total = sqrt( $sums[0] * $sums[0] + $sums[1] * $sums[1] + $sums[2] * $sums[2] );
        print "$sums[0], $sums[1], $sums[2], $total\n";
        @sums = ();
    }
}

答案 1 :(得分:1)

添加行计数器并将$totalprint代码移动到条件下的循环中。你还需要清除那里的总和。​​

if ($lines % 9 == 0) {
    ...
}

答案 2 :(得分:0)

使用输入行号$.确定每9行的时间:

use strict;
use warnings;
use autodie;

use List::Util qw(sum);

#open my $fh, '<', "file.xyz";
my $fh = \*DATA;

my @sums;

while (<$fh>) {
    my @cols = split ' ';
    for my $i ( 0 .. $#cols ) {
        $sums[$i] += $cols[$i];
    }

    if ( ( $. % 9 ) == 0 or eof ) {
        my $weighted_total = sqrt sum map $_**2, @sums;
        print join( ', ', @sums, $weighted_total ), "\n";
        @sums = ();
    }
}

warn "FH did not end an on even multiple of 9" if $. % 9;

__DATA__
-0.485718003092488 3.25568455554021 -0.60544991716881 
-1.01253068155602 -2.49251542491767 0.713923699625837
0.791137982988487 -2.56492609246597 -0.853251541212567
-0.485718003092488 3.25568455554021 -0.60544991716881
-1.01253068155602 -2.49251542491767 0.713923699625837
0.791137982988487 -2.56492609246597 -0.853251541212567
-0.485718003092488 3.25568455554021 -0.60544991716881
-1.01253068155602 -2.49251542491767 0.713923699625837
0.791137982988487 -2.56492609246597 -0.853251541212567
-0.485718003092488 3.25568455554021 -0.60544991716881
-1.01253068155602 -2.49251542491767 0.713923699625837
0.791137982988487 -2.56492609246597 -0.853251541212567
-0.485718003092488 3.25568455554021 -0.60544991716881
-1.01253068155602 -2.49251542491767 0.713923699625837
0.791137982988487 -2.56492609246597 -0.853251541212567
-0.485718003092488 3.25568455554021 -0.60544991716881
-1.01253068155602 -2.49251542491767 0.713923699625837
0.791137982988487 -2.56492609246597 -0.853251541212567

输出:

-2.12133210498006, -5.40527088553029, -2.23433327626662, 6.22167569349391
-2.12133210498006, -5.40527088553029, -2.23433327626662, 6.22167569349391

答案 3 :(得分:-1)

整个Perl-golf风格的东西,用一些空白和缩进来淡化:

while (<>) {
    @l = split;
    @s = map { $s[$_] + $l[$_] } 0..$#l;
    next if ++$n % 9;
    $, = ' ';
    print @s, sqrt(eval join '+', (map { $_*$_ } @s)), "\n";
    @s = ();
}

一些真正的Perl-golf,受到@Nemo的启发,但更短:

perl -lanE '$s[$_]+=$F[$_]for 0..$#F;$.%9&&next;print"@s @{[sqrt eval join qq(+),map $_**2,@s]}";@s=()'

找到使用过的技巧留给读者练习。 : - )