哈希

1.什么是哈希?

哈希是一种数据结构,和数组类似,可以将值存放到其中,或者从中取回值。但是,和数组不同的是,其索引不是数字,
而是名字。也就是说,索引(这里,我们将它叫key)不是数字而是任意的唯一的字符串.

 

 

2.哈希元素的存取

要访问hash元素,可以使用下面的语法:
$hash{$some_key}

这和访问数组元素的方法有些类似,这里下标(key)上使用的是花括号({}),而不是方括号([ ])◆。现在key的表达式是字
符串,而非数字:

$family_name{“fred”} =“flintstone”;
$family_name{“barney”} =“rubble”

 

我们如下的书写代码:
foreach $person (qw<barney fred>){
print“I’ve heard of $person $family_name{$person}.\n”;
}

当在名字前面是美元符号($),后面是花括号({}),则其为hash元素。

 

2.1作为整体的hash

要引用整个hash,使用百分号(“%”)作为前缀。前面使用的hash的名字为%family_name。
为了方便,hash可以转换为列表,或者反过来。给hash赋值其类型属于列表context赋值,其中列
表是key/value对◆:

%some_hash = (“foo”,35, “bar”,12.4,2.5, “hello”, “wilma”,1.72e30, “betty”, “bye\n”);

 

hash的值(在列表context中)是一个key/value对的列表:
@array_array = %some_hash;

我们把这称为:将hash展开,并将其key/value对返回到一个列表中。返回的key/value顺序和存放的顺序可能不同:

虽然key/value对的顺序是杂乱的,但返回的列表中每一个key和其value是连在一起的。

 

2.2 Hash 赋值

很少这样做,但可以使用如下的语法在hash之间拷贝:
%new_hash = %old_hash;

这段代码告诉Perl将%old_hash展开成key/value的列表,再将其赋给%new_hash,其将key/value对一个一个加入
的。

将hash转变成其它形式更加常见。例如,我们可以将hash反转:
%inverse_hash = reverse %any_hash;

这会将%any_hash展开成key/value 对的列表,其列表如(key,value,key,value,key,value,… …)。然后,将其反转,得到
(value,key,value,key,value,key,… …)。value 和key 的位置交换了。当将其存放在%inverse_hash,我们就可以查询对于
%any_hash来说是value的字符串,因为现在它对于%inverse_hash来讲是key了。查询到的value对于%any_hash来讲属于
key。这给我们提供了一种方法:查询“value”( 现在成了key),得到“key”(现在成了value)。

你可能猜测(按照科学的方法,如果你足够聪明)这仅当值也是唯一的情况才能正常工作。否则,我们将得到重复的key,
但key必须是唯一的。这里有一条规则:最后一次赋值获胜。也就是说,列表中后面的元素将覆盖掉以前的元素(相同key
时)。由于我们并不知道key/value对的顺序,因此也不能判断哪一对将最终获胜(被使用)。如果想使用这种技术,那你必
须确保之前的值是唯一的◆。如我们在早期的IP address 和hostname的例子中就可以使用:

 

2.3 大箭头符号(=>)

如果Perl能提供一种方法,让我们轻易的辨别出哪一个是key,哪一个是value,那该有多好?Larry也想过这个问题,因
此发明了大箭头符号(=>)◆。对于Perl来讲,其作用和和逗号(,)类似,因此有时称作“胖逗号(fat comma)”。Perl语法
中,在需要逗号(,)的时候,都可以使用大箭头符号替换;对于Perl来讲,它们是一样的◆。下面是给hash赋值的另一
种方法:

my %last_name = (
“fred” => “flintstone”,
“dino” => undef,
“barney”=> “rubble”;
“betty”=> “rubble”,
);
上面代码中,很容易辨别出哪一个是key,哪一个是value。注意列表中最后一个逗号。我们早期讨论过,这个逗号是没什
么用的,但有时能给我们带来方便;如果我们要加入新的元素到hash中,我们只需知道每一行都有key/value对,结尾有
逗号。Perl会查看不同元素之间的逗号,以及列表结尾处的逗号(此逗号非必需的)。

 

3.哈希函数

3.1 keys和values函数

keys函数会返回此hash的所有keys,values函数将返回所有的values。如果hash中没有元素,则此函数将返回空列表:
my %hash = (“a”=>1,“b”=>2,“c”=>3);
my @k = keys %hash;
my @v = values %hash;

现在,@k含有“a”, “b”, “c”,而@v含有1, 2, 3,其顺序可能不同。记住,Perl并不维护hash中元素的顺序。但,其中keys
按照某种顺序存储,则其对应的values也是这个顺序:如果“b”排在keys的最后,则2也排在values的最后。如果“c”是
第一个,则3也是第一个。这种论断是正确的,如果没有对keys或values做什么修改。如果添加了新元素到hash中,Perl
会重新对它们进行排序,以便能更快速的访问它们。在标量context 中,这些函数返回hash中元素的个数(key/value)。此
类操作不需要访问hash的每一个元素,其效率是很高的:
my $count = keys %hash; #得到3,是指有3个key/value 对

 

3.2 each函数

如果想迭代hash的每一个元素(如,检查每一个元素),一种通常的方法是使用each函数,它将返回key/value对的2元素
列表◆。当对同一个hash函数进行一次迭代时,将返回下一个key/value对,直到所有的元素均被访问。如果没有更多的
key/value对,则each函数将返回空表。

◆另一种方法是使用foreach,这将在本节末尾介绍。

实践中,一般只在while循环中使用each:
while (($key, $value) = each %hash){
print“$key => $value\n”;
}上述代码中,首先,each %hash将从hash中返回一个key/value 对;假设key为“c”,value为3,则列表为(“c”,3)。这个
列表赋给($key, $value),现在$key为“c”,而$value为3。

但上述赋值语句是作为while循环的条件表达式,这是在标量context中。(更确切的说,这是boolean context,其希望得到
true/false 值,但boolean context是一种特殊的标量context)。列表赋值语句在标量context中返回的是元素的个数,在本例
中,是2。由于2是一个true 值,我们进入循环,然后输出c=>3。

 

当然,each返回的key/vlaue对,顺序是混乱的(它其顺序和keys和values函数返回的顺序相同)。如果想将其按序排放,
可以对它们排序(使用sort),大致如下:

foreach $key (sort keys %hash){
$value =$hass{$key};
print“$key => $value\n”;
#也可以不使用额外的临时变量$value
#print“$key => $hash{key}\n”;
}

 

4.哈希的通常用法

假设一个叫做Bedrock的图书馆使用Perl程序,其中有一个hash对借阅者借的书的数量进行跟踪:
$books{“fred”} = 3;
$books{“wilma”} = 1;
很容易知道hash的某个元素是true 还是false,像下面这样:
if($books{$someone}){
print“$someone has at least one book checked out.\n”;
}

4.1 exists函数

要查看hash中是否存在某个key(某人是否有借书卡),可以使用exists函数,如果hash中存在此key,则返回true,这和
是否有对应的value无关:

if(exists $books{$dino}){
print“Hey, there’s a libaray card for dino!\n”;
}

4.2 delete函数

delete函数将某个给定的key(包括其对应的value)从hash中删除。(如果不存在这个key,则什么也不做;不会有警告或者
错误信息。)
my $person = “betty”;
delete $books{$person}; #将$person的借书卡删除掉

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值