2011-03-08 70 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