2009-11-30 211 views
50

我想正確理解Perl中的哈希。我不得不間歇地使用Perl一段時間,大多數時候我需要這樣做,它主要與文本處理有關。我不得不處理哈希,它會變得混亂。我發現這個語法對於哈希來說非常神祕Perl中的哈希和哈希引用有什麼區別?

哈希和哈希引用的一個很好的解釋,它們的不同之處,當它們是需要的時候,會非常感激。

+35

_ *給你一個蘋果* _假裝這是一個散列。 _ *指着你向冰箱裏的蘋果書面指示* _這是一個散列參考。 – 2009-11-30 02:37:55

+2

你可以看看_Learning Perl_有關哈希的章節。 – 2009-11-30 07:46:45

+0

@〜庸醫:我希望這是一個答案,而不是一個評論,以便我可以正確地爲你提供幫助。 – 2009-11-30 13:47:54

回答

78

一個簡單的散列靠近一個數組。他們的初始化甚至看起來相似。首先數組:

@last_name = (
    "Ward", "Cleaver", 
    "Fred", "Flintstone", 
    "Archie", "Bunker" 
); 

現在,讓我們代表了一個哈希(又名關聯數組)相同的信息:

%last_name = (
    "Ward", "Cleaver", 
    "Fred", "Flintstone", 
    "Archie", "Bunker" 
); 

雖然它們具有相同的名稱,數組@last_name和散列%last_name是完全獨立的。

與陣列,如果我們想知道阿奇的姓氏,我們必須執行線性搜索:

my $lname; 
for (my $i = 0; $i < @last_name; $i += 2) { 
    $lname = $last_name[$i+1] if $last_name[$i] eq "Archie"; 
} 
print "Archie $lname\n"; 

與散列,它更直接的語法:

print "Archie $last_name{Archie}\n"; 

說我們想用僅稍微更豐富的結構來表示信息:

  • 切割器(姓)
    • 沃德(名字)
    • 六月(配偶的名字)
  • 打火石
    • 弗雷德
    • 威爾瑪
  • 邦克
    • 阿奇
    • 伊迪絲

引用出現之前,平鍵 - 值哈希是對我們能做的最好的,但是引用允許

my %personal_info = (
    "Cleaver", { 
     "FIRST", "Ward", 
     "SPOUSE", "June", 
    }, 
    "Flintstone", { 
     "FIRST", "Fred", 
     "SPOUSE", "Wilma", 
    }, 
    "Bunker", { 
     "FIRST", "Archie", 
     "SPOUSE", "Edith", 
    }, 
); 

內部,鍵和值%personal_info都是標量,但值是一種特殊的標量:哈希引用,用{}創建。這些參考使我們能夠模擬「多維」哈希。例如,我們可以通過

$personal_info{Flintstone}->{SPOUSE} 

注意,Perl的允許我們省略下標之間的箭頭到達威爾瑪,因此上述相當於

$personal_info{Flintstone}{SPOUSE} 

,如果你想知道這是一個很大打字更多關於弗雷德,所以你可能會搶引用作爲排序的光標:

$fred = $personal_info{Flintstone}; 
print "Fred's wife is $fred->{SPOUSE}\n"; 

因爲$fred在上面的代碼片段是hashref,箭頭是必要的。如果你離開它,但明智地啓用use strict,幫助您捕捉這類錯誤,編譯器會抱怨:

Global symbol "%fred" requires explicit package name at ... 

的Perl引用類似於C和C++指針,但他們永遠不能爲空。 C和C++中的指針需要解引用,所以在Perl中引用也是如此。

C和C++函數參數具有按值傳遞的語義:它們只是副本,所以修改不會返回給調用者。如果你想看到更改,你必須傳遞一個指針。你可以用引用這個效果在Perl:

sub add_barney { 
    my($personal_info) = @_; 

    $personal_info->{Rubble} = { 
     FIRST => "Barney", 
     SPOUSE => "Betty", 
    }; 
} 

add_barney \%personal_info; 

沒有反斜槓,add_barney會得到多數民衆贊成儘快扔掉作爲子返回一個副本。

還請注意使用上面的「胖逗號」(=>)。它自動引用其左側的字符串,並使得哈希初始化的語法更少。

+0

在7年後下降,注意到C和C++允許不使用指針來傳遞引用。 'void f(DataType&arg)'通過引用傳遞'arg',並且不需要解引用來訪問或修改。 – 2016-07-04 19:20:44

+0

@JimV那時候你傳遞一個_reference_,用'&'聲明,這是一種別名。語義_is_傳遞值。 – zdim 2016-09-30 23:27:19

+0

一個偉大的職位:)。一個評論 - 或許一個警告提示值得注意的是'@ _'別名參數,所以一個_can_可以改變它們的子地址(散列鍵除外)? – zdim 2016-10-01 07:25:55

10

哈希是Perl中的基本數據類型。 它使用鍵來訪問其內容。

散列ref是​​對散列的引用的縮寫。參考文獻是 標量,這是簡單的值。它基本上是 一個標量值,其實際上包含 ,它指向實際的散列本身。

鏈接:difference between hash and hash ref in perl - Ubuntu Forums

的差異也是在語法刪除。像C,Perl的工作原理是這樣的哈希值:

delete $hash{$key}; 

和哈希引用

delete $hash_ref->{$key}; 

Perl Hash Howto是一個很好的資源,瞭解哈希值,而使用哈希引用哈希

也有另一種鏈接here that has more information on perl and references

6

請參閱perldoc perlreftut也可以在您自己的計算機的命令行上訪問。

的引用是指整個陣列或整個哈希(或其它任何東西)的標量值。名稱是您已經熟悉的一種參考。想想美國總統:一團混亂,不便的血與骨頭。但是要談論他,或者在計算機程序中代表他,所需要的只是簡單,方便的標量字符串「Barack Obama」。

Perl中的引用就像數組和哈希的名稱。它們是Perl的私有名稱,所以你可以確定它們是明確的。與「巴拉克奧巴馬」不同,參考只涉及一件事,而且你總是知道它是指什麼。如果你有一個數組的引用,你可以從它恢復整個數組。如果你有一個散列引用,你可以恢復整個散列。但是這個參考仍然是一個簡單而緊湊的標量值。

+0

@ mjp66答案的重要部分是使用'perldoc perlreftut',它與OP的計算機上'perl'一起安裝。對於OP所使用的特定版本的perl *而言,這總是最準確的文檔。鏈接僅包含在禮貌中。因此,從這個意義上說,Perl文檔URL就像引用。鏈接中的內容可能會更改,但鏈接始終指向「Perl參考教程」。並非所有鏈接都是平等的。僅供參考。 – 2016-03-05 17:02:38

15

下面演示瞭如何使用哈希和哈希參考:

my %hash = (
    toy => 'aeroplane', 
    colour => 'blue', 
); 
print "I have an ", $hash{toy}, " which is coloured ", $hash{colour}, "\n"; 

my $hashref = \%hash; 
print "I have an ", $hashref->{toy}, " which is coloured ", $hashref->{colour}, "\n"; 

另見perldoc perldsc

+8

就我個人而言,我發現看到術語'%hash'來描述一個哈希值時會感到困惑。將'%hash'重新標記爲'%favorite'可能是一個好主意,只是爲了將這一點引入家庭。然後print語句就像'print'一樣我最喜歡的玩具是$ favorite {toy}「;' – Zaid 2009-11-30 03:26:42