hash類型
hash類型也稱為字典、關聯數組、映射(map)等等,其實它們都是同一種東西:鍵值對。每一個Key對應一個Value。
- hash會將key/value散列后,按序放進hash桶。散列后的順序和存放數據的順序無關
- hash類型的key只能是字符串,value可以是字符串、數值、undef或其它類型的標量
- hash的key必須唯一,不能重復
- perl中使用符號
%
表示hash類型,如%myhash
。使用$hashname{index}
訪問hash中的元素 - perl中可以單獨對每一個hash元素賦值,也可以以列表的方式一次性賦多個值(初始化時可用)
- 一次性賦值多個時,每個value跟在自己的key后面,用逗號分隔,每個key/value對之間也使用逗號分隔
- 也就是說,它們的順序是:
{鍵1,值1,鍵2,值2...}
- 也就是說,它們的順序是:
- perl中可用使用"胖箭頭"(
=>
)替代逗號,讓整個hash看起來很清晰 - 訪問hash中不存在的元素,會返回undef
$phone_num{longshuai}="18012345678";
$phone_num{xiaofang}="17012345678";
$phone_num{fairy}="16012345678";
等價於以下幾種方式:
%phone_num1=("longshuai","18012345678", # 注意是括號,不是大括號
"xiaofang","17012345678",
"fairy","16012345678");
my %phone_num1=("longshuai" => "18012345678", # 將hash聲明為局部hash
"xiaofang" => "17012345678",
"fairy" => "16012345678");
- 使用胖箭頭賦值的時候,如果key命名夠規范(字母、數字、下划線),可以省略key部分的引號,perl會自動加上。在引用hash中的元素時,也一樣可省略引號。如
$phone_num{"longshuai"}
和$phone_num{longshuai}
都有效
%phone_num1=(longshuai =>"18012345678",
xiaofang =>"17012345678",
fairy =>"16012345678");
如果key命名不夠規范,則不會自動加上引號。有時候,這可能會當作一個表達式進行計算:
$myhash{foo.bar} # $myhash{foobar}
- 可以將hash賦值給另一個hash
%hash_name1 = %hash_name2;
Perl中的這個賦值過程和一般語言不太一樣,它會先將%hash_name2
展開成列表,然后再將這個列表賦值給新列表%hash_name1
。
- 可以直接輸出hash,如
print %myhash
,但不能加上引號,例如print "%myhash"
不會輸出hash里的元素
%myhash = (key1,value1,key2,value2,key3,value3);
print %myhash,"\n";
print "%myhash","\n";
- perl中的ENV:perl可以通過ENV這個hash直接訪問操作系統的環境變量
print $ENV{PATH}; # 輸出操作系統的PATH環境變量
如果perl想訪問操作系統中某個變量,可以直接在操作系統中設置,然后通過perl訪問:
$ myvar=2;export myvar;
print $ENV{myvar};
hash相關函數
主要有reverse()、keys()、values()、exists()和delete()。
- 可以用reverse函數反轉hash。它會將hash當作列表一樣反轉,然后再將其當作hash。所以,原hash的key會變成后來的value,原value會變成后來的key
(key1,value1,key2,value2,key3,value3)
反轉過程中:
(value3,key3,value2,key2,value1,key1)
反轉后新的hash可能之一:
(value2,key2,value1,key1,value3,key3)
因為反轉為新的hash時,是以原來的value當作新的key,所以可能會有重復的新key,perl采取的是覆蓋生效:后存儲的覆蓋先存儲的。
再者,反轉為新的hash時,會對新的key重新hash計算存儲到hash桶里,所以反轉后的順序不一定真的是反序的。這里的reverse更注重key/value的反轉。
- keys函數和values函數,分別返回key列表和value列表
- keys函數和values函數在標量上下文中返回的是列表元素的個數
%myhash = (key1,value1,key2,value2,key3,value3);
@keys = keys %myhash;
@values = values %myhash;
$keys_num = keys %myhash;
print @keys,"\n";
print @values,"\n";
print $keys_num,"\n"; # 返回3
顯然,key列表和value列表的順序和存儲的順序可能是不一致的,但至少keys函數返回的列表中,如果key1排在最前,那么values函數返回的列表中,value1也肯定排在最前
- 只要hash中包含任何一個鍵值對,在於布爾值判斷上就返回真
if(%hash){
print "True\n";
}
- exists()函數判斷hash中是否存在某個key
- delete()函數用於刪除某個key/value,如果要刪除的key/value不存在,則直接返回,不會報錯
遍歷hash
- each可以遍歷hash。each可以遍歷數組和hash,它會獲取索引和對應的值
- each每次都獲取一個鍵值對,並作上位置標記,以便下次從此開始繼續遍歷。換句話說,數組和hash有內部的迭代器
- foreach也可以遍歷hash,但它只能通過keys函數來遍歷Key,間接遍歷hash
%myhash = (key1,value1,key2,value2,key3,value3);
# each迭代遍歷
while (($key,$value) = each %myhash){
print "$key: $value","\n";
}
# foreach迭代遍歷
foreach my $key (sort keys %myhash){
print $key,$myhash{$key},"\n";
}
需要注意的是each遍歷,是不保證順序的,foreach可以按照一定keys的順序進行遍歷。另外,在上面while each迭代的過程中,有幾個過程:
each %myhash
首先迭代第一個鍵值對;- 將獲取到的第一個鍵值對賦值給
($key,$value)
; - 判斷
while
的條件真假,因為賦值后得到的是一個包含鍵、值的列表,在while的標量上下文中,它返回列表中元素數量2,所以為真; - 迭代到最后一個,each迭代不到key/value,所以列表元素數量為0,while的條件返回false,不會繼續執行下去。