2011-03-08 66 views
0

我有一个文本文件,其中包含以空行分隔的数字列表,如下所示 - 我想添加所有第一个(20.187 + 19.715 + 20.706 ...),第二个元素(15.415 + 14.726 + 15.777)等 得到总的每个元素月1日,2日,3日等添加数组列表perl

20.187 15.415 8.663 6.001 6.565 6.459 6.564 .. 

19.715 14.726 8.307 5.833 6.367 6.089 6.444 .. 

20.706 15.777 9.185 6.546 7.327 7.172 7.084 ... 

,因为它们是* 不按列排列 *我怎么能加起来数组中的元素。

+1

您编辑为强调“不按列排列”......我不明白这一点。你在问如何将每一行的所有第N个元素加在一起(以下所有答案都会显示)。那“不按列排列”是如何? – 2011-03-08 18:57:20

+0

@Brian Roach:我的猜测是他的意思是这些列不是固定宽度的。然而,'split'在分隔符上运行,而不是固定的宽度。 – 2011-03-08 19:00:12

+0

这些数字被排列成多行,如果他们多说300或多个空格分隔的话,那么在每个块/组中,每个列可以有多个来自每个组的数字。不会工作 – user631148 2011-03-08 19:04:27

回答

6

使用split获取所有字段。跟踪数组中的运行总数(其索引映射到文件中的列)。

事情是这样的:

while (<$file>) 
{ 
    chomp; 
    my $index = 0; 
    $total[$index++] += $_ for split; 
} 

注意split按空白进行分割默认。如果你喜欢,你可以使用其他分隔符。


编辑:这个答案是可悲的是没有用的,现在这个问题已经得到澄清。改用Brian Roach的回答。

+0

我不知道'for'的语法。甜。 – Mat 2011-03-08 18:48:53

+1

@Mat:任何循环语句都具有此功能,您可以在其中根据循环修改任何单个语句的执行流程。如果你想要多个语句,显然你需要使用一个块。 (你也可以使用'do {#block} while $ condition'和类似的东西,但是有时你会得到不同的行为。do-while将会执行一次,就像在C中一样,但是语句 - 虽然会像普通的while循环一样工作。所以我通常只使用'while'{#block}'或'statement'while $ condition',除非我特别需要do-while功能。清除泥浆? :-) – 2011-03-08 18:52:30

+0

@Mat:呵呵,当你在单个语句中做循环后缀时,你不能使用'$ _'之外的任何循环变量。这是唯一的陷阱。 – 2011-03-08 18:54:19

2

你可以尝试这样的事:

my @sum; 
while (<>) { 
    chomp; 
    my @items = split /\s+/; 
    for (my $i=0; $i<@items; $i++) { 
     $sum[$i] += $items[$i]; 
    } 
} 

$sum[$i]将包含总$i列。

或者稍微“Perl化”:

my @sum; 
while (<>) { 
    chomp; 
    my @items = split; 
    for my $i (0 .. $#items) { 
     $sum[$i] += $items[$i]; 
    } 
} 
+0

无论如何,这个答案可能比我的更清晰,现在我看着它。 :-)(+1)我利用了大量的Perl默认值,比如没有参数和单个语句的'split'。 – 2011-03-08 19:01:19

+0

你有我的(+1) - 循环中的C风格在perl中总是看起来很怪异(IMO)。 – Mat 2011-03-08 19:13:17

5

编辑:从澄清的问题,需要处理的空行和可能性,一系列的数字被打破多行。

my @totals; 
my @currentVals; 

while (my $line = <FILE>) 
{ 
    chomp($line); 
    if ($line eq "") 
    { 
     for ($i = 0; $i < @currentVals; $i++) 
     { 
      @totals[$i] += @currentVals[$i]; 
     }  
     @currentVals =(); 
    } 
    else 
    { 
     push @currentVals, split(' ', $line); 
    } 

} 

这应该做你想找的。你需要继续添加到currentVals数组中,直到你找到一个空行,然后做数学。

+0

@ user631148:这是正确的答案,现在问题已被澄清。请不理我的答案。 – 2011-03-08 20:59:20

3
use strict; 
use warnings; 

# Paragraph mode (so that blank lines become our input delimiter). 
local $/ = "\n\n"; 

my @totals; 

while (<>){ 
    my $i; 
    $totals[$i++] += $_ for split; 
} 
+0

这当然是“perl的方式去做”。除了你用一个评论来实际解释这个技巧;) – 2011-03-08 20:12:35

+0

哦,快点。这绝对会做到! (1) – 2011-03-08 21:00:12