2011-08-08 87 views
3

看起來很簡單,我想到了它的大部分。但是看到perl語法鬆散,對於新來者來說很難跳到:)試圖理解這個perl腳本

my @unique =(); 
my %seen =(); 
foreach my $elem (@array) { 
    next if $seen{ $elem }++; 
    push @unique, $elem; 
} 

這是來自perldoc網站。如果我理解正確的話,也可以寫爲:

my @unique =(); 
my %seen =(); 
my $elem; 
foreach $elem (@array) { 
    if ($seen{ $elem }++) { 
     next; 
    } 
    push (@unique, $elem); 
} 

所以我在這一點上的認識是:

  • 聲明一個名爲獨特的數組
  • 聲明名爲看到
  • 申報哈希一個名爲elem的變量
  • 迭代@array,每次迭代都存儲在$ elem中
  • 如果$ elem是散列中的一個鍵%看到(我不知道是什麼++一樣),跳到下一個迭代
  • 追加$ ELEM到@unique

末我失去了兩兩件事:

  • 當是否有任何內容以%顯示?
  • 什麼++做(在它增加所有其他語言,但我沒有看到它是如何工作)

我知道,問題在於這部分:

$seen{ $elem }++ 

我懷疑正在做一堆不同的東西。是否有更簡單更詳細的寫作方式?

感謝您的幫助

回答

4

++運營商確實基本上是同樣的事情在Perl作爲它有它大多數其他語言的作用:它增加一個變量。

$seen{ $elem }++; 

遞增的%seen的值了,即其主要是$elem之一。

「魔術」是,如果$seen{$elem}尚未定義,它會自動創建,就好像它已經存在並且值爲0;在++然後將其設置爲1,因此,這等同於:

if (! exists $seen{$elem}) { 
    $seen{$elem} = 0; 
} 
$seen{$elem} ++; 

這就是所謂的「自動激活」。 (編輯2:不,我的錯誤,它不是;正如@ysth指出的那樣,「autovification」實際上是指參考文獻的存在,見perldoc perlref。)

編輯:這是你的描述的修訂版本:

  • 聲明一個名爲@unique
  • 數組變量聲明見過
  • 一個散列變量名爲%聲明一個標量變量命名爲$ elem
  • 迭代@array,每次迭代存儲在$ elem中
  • 如果$ ELEM是出現在哈希%的關鍵,跳到下一個迭代
  • 追加 $ ELEM來的@unique

@unique%seen$elem末的值都變量。標點字符(稱爲「印記」表示什麼類型的變量,他們每個人的是,而且是最好的思想作爲其名稱的一部分。

+0

啊我覺得有什麼可疑的。編寫具有大量自動版本的代碼是否是一種好的做法?還是長時間寫出來更好? – n0pe

+2

@MaxMackie:在自動編寫代碼時沒有任何問題 - 它被編碼到Perl中的原因是因爲Larry Wall知道這是一個有用的模式。一旦你意識到了這一點,這很有道理。在這樣的代碼中,你只是對散列值進行數字運算,所以將散列中的值視爲從0開始就是合理的。你只是檢查真值(非零),從不檢查因此這是一個好的假設,它可以讓你簡化你的代碼。 –

+0

完美,謝謝你的幫助。我會在2分鐘內接受。 – n0pe

3

什麼時候的事有任何存儲在%見過?

當它試圖增加它。

什麼++做(在它增加所有其他語言,但我沒有看到它是如何工作)

遞增未定義的變量使得1

它確實與此相同:

my @unique =(); 
my %seen =(); 
my $elem; 
foreach $elem (@array) { 
    if (! $seen{ $elem }) { 
     $seen{ $elem } = 1; 
    } else { 
     $seen{ $elem }++; 
     push (@unique, $elem); 
    } 
} 
1

如果在%沒有元素與鍵$ ELEM看到那麼這條線將創建一個新的元素(新輸入哈希表)與關鍵$ elem。 ++之後是一個增量運算符。它增加了$看到{$ elem}的價值。由於$ seen {$ elem}的初始值在數值上下文中計算爲false或零,因此這會使$ seen {elem}的值增加1。由於++位於$ seen {$ elem}的右側,因此只會在$ seen {elem}被評估之後添加。因此,第一次遇到任何特定元素時,此測試將失敗並進入下一步,將$ elem放入獨特元素的列表(數組)中。

3

這是Perl中用於創建由給定數組中的「unique」元素組成的數組的常用模式。

在Perl中,散列存儲與任何給定鍵相關聯的值。但是,如果您沒有爲給定密鑰輸入任何內容,則會得到undef - 但是在數字上下文中,例如當您執行增量操作時,undef被視爲0,然後遞增。如您所知,if語句會檢查真值或假值。在Perl中,0,"0",''(空字符串)和undef(可能還有其他?)被視爲假值。

後增加,就像在C/C++/Java中一樣,將原始值返回到包含表達式。所以這段代碼

if ($seen{ $elem }++) { 
     next; 
    } 

將返回false(0)對於尚未見過的元素,並且循環將繼續(即next語句不會運行)。該元素將被放入數組中。但是在此之前,增量會發生 - 現在突然1被存儲在散列中,意味着該值已被查看過一次。下次看到該值時,循環將被跳過,並且該值不會再次添加到結果數組中。