2012-11-08 46 views
2

當運行一個簡單的代碼位是這樣的:如何在不更改循環變量的地址的情況下使用foreach迭代數組?

my @arr=(1..5); 
my $x; 
foreach $x (@arr) { 
    $x+=10; 
} 
print "@arr"; 

的結果是「11 12 13 14 15」,因爲$ X「變爲」在foreach的@arr陣列中的每個元件。足夠好。

但是,這是我的事...沒有這麼多的問題(解決方案很簡單,但不雅,我希望我的Perl儘可能優雅)。

我寫了一個處理COBOL數據的綁定模塊。它需要一本字典,解析字段,然後將其附加到標量/字符串,以便對綁定散列的訪問將返回/設置字符串中的值。它奇妙地工作。

my %h,$rec; 
my $cb=<<END; 
     01 CH-RECORD. 
      05 JOB-NUM PIC X. 
      05 FILLER PIC X(76). 
      05 REC-TYPE PIC X(2). 
END 
tie %h, 'COBOLDataTie',$cb,\$rec; #tie the hash to the record via the copybook 

從那裏,我可以移動COBOL記錄$ REC和與%H哈希訪問COBOL領域。

再一次,這完美的作品。但是當我想迭代COBOL記錄數組時,問題就出現了。所以,如果上面的代碼後,我有一個類似於:

foreach $rec (@arr) { 
    print "Job is ",$h{'JOB-NUM'},"\n"; 
} 

它不會工作,因爲在foreach實際上改變$錄製,打破上領帶的位置。我最終不得不做這樣的事情:

foreach (@arr) { 
    $rec=$_; 
    print "Job is ",$h{'JOB-NUM'},"\n"; 
} 

有什麼辦法,我可以做「的foreach $ REC(@arr)」,並沒有打破我綁哈希?

(和任何人說,以前,是的,我知道這引出了一個不錯的面向對象的解決方案......有一天我會去說,我只需要找到一些時間第一)

後記:我修改了TieHash代碼,而不是指向外部記錄,它攔截了散列的「特殊」鍵,其中有'記錄'。所以,當我將一個記錄字符串賦值給$ h {'record'}時,它與上例中的加載$ rec相同。這是一個更好的解決方案,更獨立。它也暴露了一個更類似於OOP的界面。

+0

@ikegame我想我看到什麼OP手段。看看第二個代碼塊。不知何故,他正在將'$ rec'綁在哈希上。 – simbabque

+0

爲什麼你使用['tie'](http://perldoc.perl.org/functions/tie.html)模塊?如何比只使用一個對象更好? –

+0

正如我所指出的,我還沒有完成OOP版本......也許有一天,如果我的工作量減輕了。 @simbabque,我實際上綁定到\ $ rec,而不是$ rec。 – mswanberg

回答

0

這似乎是最好的辦法是做這樣的事情:

for (my $i=0;($rec=$arr[$i], $i<@arr);$i++) { 

不完全是優雅我所期待的,但它似乎工作。

2

您決定創建的界面是「分配到$rec,然後通過%h訪問字段」。因此,這正是你需要做的。

for (@arr) { 
    $rec = $_; 
    print "Job is $h{'JOB-NUM'}\n"; 
} 

確定它看起來很奇怪,但那是因爲它很奇怪。這將使更加合理:

for (@arr) { 
    my $h = parse($cb, $_); 
    print "Job is $h->{'JOB-NUM'}\n"; 
} 

,你甚至可以以最小的變化做到這一點:

sub parse { 
    my ($cb, $rec) = @_; 
    tie my %h, 'COBOLDataTie', $cb, \$rec; 
    return \%h; 
} 
+0

您的建議的缺點是每條記錄都必須每次都解析每個字段。在具有數百個字段,其每一個必須從COBOL格式解構爲常規標量(可能包括,EBCDIC到ASCII轉換),如果我只需要1個或2個字段中的記錄,該方法將一個記錄大大減緩處理時間。使用連結哈希允許代碼只在使用時轉換字段,而不必轉換所有字段。根據你的建議,我之前在這方面的努力的確具有解析功能。 – mswanberg

+0

哎呀,是的,這不等同。 – ikegami

+0

更合理的綁定數組API可能是'綁定我的%h','COBOLDataTie',$ cb; $ H $ {錄音} { 'JOB-NUM'}'。 '$ h {rec}'需要將一個ref返回給一個並列散列。 – ikegami

2

這是一個foreach變量細微之處,易於在文檔中忽略,但循環變量總是一個新變量,並且與程序中任何其他地方的任何詞彙或包變量無關。

perlsyn

foreach循環

的「的foreach」過正常的列表值循環迭代並設置 變量VAR是反過來的列表的每個元素。如果變量 前面帶有關鍵字「我的」,那麼它是詞法範圍的,並且是 因此僅在循環可見。否則,變量是 隱含本地環路和在退出 循環重拾昔日的價值。如果變量先前已宣告「我的」,它使用 變量,而不是全球性的,但它仍然定位於 循環。這種隱式本地化只發生在「foreach」循環中。

(強調)。也就是說,在這個小腳本的第3行$rec無關,在1號線

1: my $rec = 'foo'; 
2: print $rec;      # 'foo' 
3: foreach $rec (@some_list) { 
4:  print $rec;     # something else 
5: } 
6: print $rec;      # 'foo' again 

所以,如果你想使用\$rec影響你綁散列的行爲(雖然肯定有其他聲明的$rec如何做到這一點),那麼你正在做正確的事情來使用不同的循環變量,並在循環內指定$rec

+0

非常好的信息,謝謝。不幸的是,我不能回答我的問題,但僅僅強化了我不能按照我想要的方式去做。 – mswanberg

相關問題