Perl入門筆記——哈希

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};
}
相關文章
相關標籤/搜索