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

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM