2010-06-01 47 views
2

我正在做一個小的datamining項目,其中perl腳本從SQL數據庫中獲取信息並對其進行分析。數據由幾個時間戳組成。我想查找某個特定日期有多少種特定類型的時間戳。 不幸的是,這是我的第一個perl腳本,當涉及到哈希和數組時,perl的本質讓我頗爲困惑。新的Perl用戶:使用陣列的散列

代碼段:

my %values=();#A hash of the total values of each type of data of each day. 
#The key is the day, and each key stores an array of each of the values I need. 
my @proposal; 
#[drafted timestamp(0), submitted timestamp(1), attny approved timestamp(2),Organiziation approved timestamp(3), Other approval timestamp(4), Approved Timestamp(5)] 
while(@proposal=$sqlresults->fetchrow_array()){ 
#TODO: check to make sure proposal is valid 
#Increment the number of timestamps of each type on each particular date 
my $i; 
for($i=0;$i<=5;$i++) 
$values{$proposal[$i]}[$i]++; 
#Update rolling average of daily 
#TODO: To check total load, increment total load on all dates between attourney approve date and accepted date 
for($i=$proposal[1];$i<=$proposal[2];$i++) 
$values{$i}[6]++; 
} 

我一直得到裏面的語法錯誤for循環遞增值。另外,考慮到我使用嚴格和警告,當我在哈希中訪問它們時,Perl會自動創建正確值的數組,還是我會在任何地方出現超出範圍的錯誤?

感謝您的幫助, 扎克

+3

這段代碼編譯? '(...)STATEMENT'通常是Perl中的錯誤。大括號是必需的 - 它需要用於(...){STATEMENT}' – mob 2010-06-01 19:21:07

回答

5

錯誤:

for($i=0;$i<=5;$i++) 
    $values{$proposal[$i]}[$i]++; 
for($i=$proposal[1];$i<=$proposal[2];$i++) 
    $values{$i}[6]++; 

Perl不支持裸環/條件塊。或者說,it does,但不是這樣的。這可能適用於PHP,但不適用於Perl。您將要在塊附上這些:

for($i=0;$i<=5;$i++) { 
    $values{$proposal[$i]}[$i]++; 
} 
for($i=$proposal[1];$i<=$proposal[2];$i++) { 
    $values{$i}[6]++; 
} 

$values{$proposal[$i]}[$i]++; 

由於在Perl哈希只能適合他們的標量數據類型,以存儲哈希的內部的整個陣列,我們將不得不通過參考來做到這一點。這裏有數組引用的快速教程:

my $arr_ref = [];    # empty array reference 
my $arr_ref = [ 1, 2, 'foo', ]; # initialize with values 
my $arr_ref = \@arr;   # reference an existing array; 
           # does not make copy, but provides a 
           # read-write handle to the array 

$arr_ref->[0];     # index the first (index 0) element of the array 
@{$arr_ref}[ 0 .. 4 ];   # index elements number one through five (0-4) of the array 
           # through what's called an "array slice" 

什麼上面的代碼做的是拉在哈希鍵$proposal[$i]值進行哈希%values的,然後用它(標量)作爲數組(它不是一個數組)。

正如我以前說過,你可以使用它作爲一個數組參考但不是一個數組:

    # v-- note the arrow 
$values{$proposal[$i]}->[$i]++; 

建議:

  • my $foo; for ($foo = 0; $foo <= 5; $foo++)更容易寫成「 for my $foo (0 .. 5)「或」foreach my $foo (0 .. 5)「。實質上,大多數人是這麼做的。值得注意的是forforeach是可以互換的–這是一個偏好和易讀性的問題。

  • 爲了便於理解,請使用多個空格縮進代碼。一個好的經驗法則是四個空格或一個製表符。當他設計Perl時,聖拉里沃爾正在思考人們說話和寫作的語言。

  • 我建議研究一下編寫for循環的正確方法(在這裏,意思是最有效的)。有一些習慣,如果他們有很多很長的for循環,會導致整個程序更快。例如:

    • ++$foo$foo++效率更高。這源於內部:
      • $foo++遞增變量,減去1,然後返回結果,而
      • ++$foo遞增變量並將其返回。更少的操作=更快。
    • 小於或等於比較比簡單小於比較效率低。同樣,這是由於您計算機必須執行的操作次數所致。 for ($x=0; $x<=5; ++$x)更好寫成for ($x=0; $x<6; ++$x)
  • Perl有一些美妙的循環控件。有些像map,功能非常強大。

+1

$ values {$ proposal [$ i]} [$ i]是非常好的。你只需要 - >箭頭在開始處解引用標量。例如:my $ arr_ref = [{a =>'f',b =>'g'},{c =>'h',d =>'i'}];打印$ arr_ref - > [0] {b}; – DougWebb 2010-06-02 03:06:48

+0

@DougWebb - 你完全正確; Perl會補償表達式中缺少' - >',即使在'use strict'中也是如此。我將保留原樣,讓OP瞭解數據結構所發生的一切。 – amphetamachine 2010-06-02 12:23:10

+1

我對現在的結構如何工作有個很好的想法。我的代碼實際上工作,並且看起來相當清潔!我仍然在搞清楚Perl做什麼,不會自動執行,但這是一個很好的推動。謝謝大家! – 2010-06-02 18:35:53