加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

Perl笔记:05、哈希

发布时间:2020-12-16 00:07:28 所属栏目:大数据 来源:网络整理
导读:什么是哈希 哈希是一种数据结构,和数组相比 相同在于 :可以容纳很多值(没有上限),并能随机存

什么是哈希

哈希是一种数据结构,和数组相比
相同在于:可以容纳很多值(没有上限),并能随机存取。
区别在于:不像数组是以数字来检索,哈希是以名字来检索。也就是说检索用的键不是数字,而是保证唯一的字符串

所谓键其实就是字符串,所以我们不必用数字3来获取数组元素,而是用vilma这个名字来存取哈希元素。

这些键可以是任何字符串……你可以用任意字符串表达式作为哈希键。它们也必须是唯一的字符串,就像数组中只能有一个编号为3的元素一样。

哈希的键与值

哈希的键与值

另一种看待哈希的方法是将它想象成一大桶的数据,其中每个数据都有关联的标签,可以伸手到桶里任意取出一张标签,查看它附着的数据时什么。但是在桶里没有所谓的第一个元素,只有一堆数据。数组中有第一个元素0,但在哈希里没有顺序,只有一些键/值对。如下图:

哈希像一桶数据

这些键和值都是任意的标量,但会被转换成字符串,如50/20为键,那么他会转换成含有三个字符的字符串“2.5”。

根据Perl“去除不必要限制”的原则,哈希可能是任意大小,从没有任何键/值的空哈希到填满整个内存的哈希都可以。由于Perl针对哈希的算法优化,与替他语言不通,Perl在操作含有三个键值的哈希和操作三百万个键值的哈希速度是一样的。

访问哈希元素

要访问哈希元素,需要使用如下语法:
$hash{$some_key}

这和访问数组的做法类似,只是使用了花括号而非方括号来引出索引。而且现在的键表达式是字符串,而非数字:

$family_name { "fred" } = "flintstone" ;
$family_name { "barney" } = "rubble" ;

我们可以在程序中这样访问哈希:

foreach $person (qw < barney fred > ) {
print "I've heard of $person $family_name{$person}.n" ;
}

哈希变量的命名和其它Perl的标识符类似,可以有字母、数字和下划线,但不可以用数字开头。哈希有自己的命名空间,也就是说程序中可以定义同名的哈希,子程序,或数组,但按照正常人的思维方式还是不要这样办的好。

访问整个哈希

要指代整个哈希,可以用百分号(%)作为前缀。因此前面我们使用的哈希应该称之为?mily_name

为了方便起见,哈希可以转换成列表,反过来也行。但当列表转为哈希时一定要确保列表中的元素为偶数个,否则的话会产生奇怪的结果。

哈希赋值

哈希的赋值可以用列表或者数组来初始化一个哈希,但这都不是最好的办法,Perl推荐使用使用“胖箭头”(=>)符号来对哈希进行赋值,如下:

my %last_name = ( # 哈希也可以是词法变量
"fred" => "flintstone" ,
"dino" => undef ,
"barney" => "rubble" ,
"betty" => "rubble" ,
) ;

这样的赋值清晰明了。列表结尾有一个额外的逗号,这种写法不但无伤大雅,而且便于维护。但需要加入更多人的信息时,只要确保每行都有一组键/值对和结尾的逗号就可以了。

哈希函数

keys和values函数
keys函数能返回哈希的键列表,而values函数返回值列表。如果哈希没有任何成员,则两个函数都返回空列表:

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存储哈希的顺序无法预测。但可以确定的是返回的键列表和值列表的顺序是一样的。在标量上下文中这两个函数都会返回哈希中键/值对儿的个数。这个计算过程不必对整个哈希进行遍历,因而非常高效:

my $count = keys %hash; # 得到 3,也就是说有三对儿键值

偶尔也能看到别人的程序里把哈希当成布尔表达式来判断真假,如下:

if ( %hash ) {
print "That was a true value!n" ;
}

只要哈希中有一个键/值对,就返回真。所以,这里的意思是如果哈希不为空就打印输出。这种写法很少见。

each函数
如果要罗列哈希的每个键/值对,可以使用each函数。它可以用两个元素的列表形式返回键/值对。每一次对同一个哈希调用此函数,他就会返回下一组键/值对,直到所有的元素都被访问过。也就是再没有任何新的键/值对,此时each会返回空列表。

实际使用时,唯一适合使用each的地方就是在while循环中,如下:

while ( ( $key , $value ) = each %hash ) {
print "$key => $valuen" ;
}

这里有很多的操作,首先,each %hash会从哈希中返回一组键/值对,结果是含有两个元素的列表。该列表会赋值给($key,$value)。while循环中每次会从%hash取出一对数据赋值给$key,$value 如果到最后没有内容了,这两个变量的就会赋值为undef,默认情况下undef的值为0,因此这时候while就会终止循环了。当然each返回键/值对的顺序是乱的,也就是说和我先前赋值的时候顺序是不一致的。但它与keys和values返回的顺序相同,也就是哈希的自然顺序。那如果要想对哈希排序怎么办呢,只要对键排序就行了。如下方法:

foreach $key ( sort keys %hash ) {
$value = $hash { $key } ;
print "$key=> $valuen" ;
# 或者可以省略变量$value
# print "$key=>$hash{key}n";
}

exists函数
若要检查哈戏中是否有某个键,可以使用exists函数,它能返回真或假,分别表示键存在与否,和键对应的值无关:

if ( exists $books { "dino" } ) {
print "Hey,there's a library card for dino!n"
}

也就是说,exists $books{"dino"}返回真,意味着dino存在于keys %books返回的键列表中。

delete函数
该函数可以删除哈希中指定的键以及其对应的值。如果没有该键,则会直接结束,不会出现仍和的警告信息。

哈希值内插
可以将单一哈希元素内插到双引号引起的字符串中:

foreach $person ( sort keys %books ) {
if ( $books { $person } ) {
print "$person has $books{$person} itemsn" ;
}
}

但整个哈希的内插是不支持的,"$books"的结果只是6个字符的串 %books

%EVN哈希
Perl既然是允许在系统中,那么它就有必要知道当前系统的一些环境。Perl是利用%ENV哈希来存储这些信息的。例如在%ENV中存取PATH键的值:

print "PATH is $EVN{PATH}n";

因此在Perl中可以从$ENV 中得到系统环境中的变量。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读