Learning Perl 第六章 哈希 哈希是一種數據結構,與數組不一樣之處在於索引方式,數組以數字來索引,哈希則以名字來索引。 哈希的索引值,稱爲鍵,並非數字,而是任意惟一的字符串。 根據Perl去除沒必要要限制的原則,哈希能夠是任意大小的,就是關聯數組(associative array)。 哈希的讀寫性能很高,值能夠是數字,字符串,undef或者組合。可是哈希的鍵必須全都是字符串。 哈希看成簡單的數據庫,問題中帶有找出重複,惟一,交叉引用,查表之類的字眼,就能夠用到哈希。 訪問哈希元素 $hash($some_key) 和訪問數組相似,只是使用花括號,而非方括號表示索引值。 $animal{'dog'} = "caoqing"; $animal{'cat'} = "xiaohuan"; foreach my $animal (qw \dog cat\) { print "I have heard of $animal $animal{$animal}.\n"; } 哈希鍵不必定是字符串或簡單標量變量,也能夠是任意的表達式。 若對某個已存在的哈希元素賦值,會覆蓋以前的值。 訪問整個哈希 指代整個哈希,能夠用%做爲前綴,%animal。 哈希能夠被轉變爲列表,列表中的元素應該爲鍵值對: %some_hash = ('cao',20,'qing',3,'wang',21); 在列表上下文,哈希就是簡單的鍵值對列表: @array = %some_hash; 這種變換成爲展開哈希。 #use 5.012; %some_hash = ('cao',20,'qing',3,'wang',21); @array = %some_hash; print "@array"; wang 21 cao 20 qing 3 順序錯亂,是由於哈希已經爲快速檢索對鍵值對的存儲作了排序,使用哈希的場合,要麼存儲順序可有可無,要麼容易在輸出是進行排序。 哈希賦值 哈希支持賦值運算符,my %new_hash = %old_hash; %old_hash會展開爲鍵值對列表,而後經過列表賦值從新構建鍵值對,造成新的哈希。 胖箭頭 將列表賦值到哈希是經常發現列表中的鍵值對不容易區分。 Perl使用胖箭頭(=>)來代替逗號。 my %animal = ( 'dog' => 'caoqing', 'cat' => 'xiaohhuan', 'pig' => 'xiaobao', ); 使用旁箭頭是能夠省略鍵的引號,左邊的部分能夠被自動引用。 無需引號的字符序列,稱爲裸字。 容許省略鍵名義好的地方是花括號中檢索指定鍵名的元素。好比$animal{'dog'}能夠簡寫爲$animal{dog}。不加引號已經成爲慣例,若是花括號內不是裸字,Perl會將其作爲表達式求值,結果做爲鍵名。 哈希函數 keys和values函數 keys函數返回哈希的鍵列表,values函數返回哈希的值列表。 my %hash = ('a' => 1, 'b' => 2, 'c' => 3,); my @k = keys %hash; my @v = values %hash; print "@k\n"; print "@v"; a b c 1 2 3 Perl會根據須要從新優化排列順序,以保持高速訪問。在標量上下文中,這兩個元素會返回哈希中的元素個數。這個過程不須要遍歷整個哈希,因此很是高效。 my %hash = ('a' => 1, 'b' => 2, 'c' => 3,); my @k = keys %hash; my @v = values %hash; my $count = @k; print "$count\t"; my $count2 = @v; print "$count2"; 3 3 哈希也能夠看成布爾值來判斷真假,至少有一個鍵值對,就返回真。 each函數 須要迭代整個哈希時,常見就是each函數,包含兩個元素的列表形式返回鍵值對每次對同一個哈希調用此函數,就會返回下一組鍵值對,直到全部的元素都被訪問過。在沒有任何鍵值對時,each函數會返回空列表。 惟一適合使用each的地方就是在while循環裏。 my %hash = ('a' => 1, 'b' => 2, 'c' => 3,); while (($key, $value) = each %hash) { print "$key => $value\n"; } c => 3 a => 1 b => 2 each返回鍵值對是亂序的,keys和values返回哈希的天然順序,若是一次處理哈希,只須要對鍵排序。 my %hash = ('a' => 1, 'b' => 2, 'c' => 3,); foreach $key (sort keys %hash) { $value = $hash{$key}; print "$key => $value\n"; } a => 1 b => 2 c => 3 哈希的典型應用 exists函數 若要檢查哈希中是否存在某個鍵,可使用exists函數,返回真假,分別表示鍵存在與否。 my %hash = ('a' => 1, 'b' => 2, 'c' => 3,); if (exists $hash{d}) { print "i love you"; } else { print "i hate you"; } i hate you delete函數 delete函數能夠從哈希刪除指定的鍵及其對應的值。假如鍵不存在,會直接結束,不出現警告信息或錯誤信息。 my %hash = ('a' => 1, 'b' => 2, 'c' => 3,); delete $hash{a}; print keys %hash; bc 哈希元素的內插 %ENV哈希 Perl程序運行環境的信息,print "PATH is $ENV{PATH}.\n"。 PATH is C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;D:\strawberry\c\bin;D:\strawberry\perl\site\bin;D:\strawberry\perl\bin;d:\Program Files (x86)\SSH Communications Security\SSH Secure Shell. 習題 1. 編程讀取用戶指定的名字而且彙報相應的姓。 2. 編程讀取單詞,而後打印列出每一個單詞出現次數的列表。 3. 編程輸出%ENV全部鍵值對,按照ASCII編碼排序。 答案 1. my %last_name = qw { cao qing xiao bao wang huan }; print "Enter a first name: "; chomp(my $name = <STDIN>); print "That is $name $last_name{$name}.\n"; 2. my (@words, %count, $word); @words = qw(i love you cao qing. you are the best people on the world!); foreach $word (@words) { $count{$word} += 1; } foreach $word (keys %count) { print "$word was seen $count{$word} times.\n"; } 3. my $longest = 0; foreach my $key (keys %ENV) { my $key_length = length($key); $longest = $key_length if $keylength > $longest; } foreach my $key (sort keys %ENV) { printf "%-${longest}s %s\n", $keys, $ENV{keys}; }