Perl中的hash類型

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_name1code

  • 能夠直接輸出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)

反轉過程當中:hash

(value3,key3,value2,key2,value1,key1)

反轉後新的hash可能之一:變量

(value2,key2,value1,key1,value3,key3)

由於反轉爲新的hash時,是以原來的value看成新的key,因此可能會有重複的新key,perl採起的是覆蓋生效:後存儲的覆蓋先存儲的。foreach

再者,反轉爲新的hash時,會對新的key從新hash計算存儲到hash桶裏,因此反轉後的順序不必定真的是反序的。這裏的reverse更注重key/value的反轉。perl

  • 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迭代的過程當中,有幾個過程:

  1. each %myhash首先迭代第一個鍵值對;
  2. 將獲取到的第一個鍵值對賦值給($key,$value)
  3. 判斷while的條件真假,由於賦值後獲得的是一個包含鍵、值的列表,在while的標量上下文中,它返回列表中元素數量2,因此爲真;
  4. 迭代到最後一個,each迭代不到key/value,因此列表元素數量爲0,while的條件返回false,不會繼續執行下去。
相關文章
相關標籤/搜索