Perl语言程序设计_哈希

本文深入解析Perl语言中的哈希概念,对比数组,介绍哈希的基本属性如键值对、无序性,以及如何访问、赋值和使用哈希函数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

哈希基本概念

在学习Perl语言的过程中,遇到了一个别的语言中并不常见的概念——哈希。哈希表并不是Perl语言特有的数据结构,但是Perl语言中的哈希具有得天独厚的优势。哈希与数组非常相似,但是也有着非常明显的不同。在一个数组当中,数组的每一个元素包含一个值,同时每一个元素都有它对应的下标。简单些说,就是数组是“值”与“数组下标”之间的对应关系,其中值可以有任意情况(可以使空、未定义、数字、字符串等等),而数组下标务必是唯一的。而哈希则是“键”与“值”之间的对应,我们可以把哈希的“键”与数组的“下标”进行类比,它们的作用是相似的。哈希的键是唯一的,而值则跟数组一样。它们之间的不同点在于,下标是从0开始递增的自然数,而哈希的键则是字符串。对此我们可以引申出一个事实——哈希是没有顺序的。在哈希中不存在数组中所谓“第几个元素”的概念,就好比是一对数据,每个数据都有对应的标签,我们只能通过标签去寻找数据,而无法通过“它是第几个元素”来对数据进行定位。

对于哈希的键,Perl语言中的上下文起到了至关重要的作用。上文中提到过,哈希的键都是字符串,因此在程序运行的过程中,不同的上下文会对哈希的键有不同的影响。例如,如果5/2存在于字符串上下文中,并把它设置为哈希的键的话,那么这个哈希的键为“5/2”;如果是在标量上下文中,则哈希的键将会是这个标量的运算结果,即“2.5”。

访问哈希元素

如果要访问哈希元素,采用的语法为:

$hash{$some_key}

其中hash是哈希表的名字,而some_key是键。对于Perl语言而言,判断一个变量是否为哈希的依据是“$符号后面有花括号”,也就是说,如果名称之前有一个美金符号,而名称之后有花括号,那么系统会认为自己访问的是一个哈希元素。

如果要访问整个哈希表,可以用百分号(%)作为前缀。Perl程序会将哈希转换成列表(反之亦然)。对哈希的每一个赋值操作实际上就是再列表上下文中赋值,且列表中的元素为键-值对。举一个《Learning Perl》上的例子:

$some_hash = (
    'foo', 35, 'bar', 12.4, 2.5, 'hello', 'wilma', 1.72e30, 'betty', 'bye\n'
)

当哈希表被转化为列表的时候,也就是在列表上下文中,这种转化称之为展开哈希,不过需要注意的是,通过这个方法得到的键值对的顺序不会是原来的顺序,而是是刻意打乱的,这样黑客就无法预知信息是如何存储的。一般选择使用哈希的场合,要么元素存储顺序无关紧要,要么可以容易地在元素输出的时候进行排序。

哈希赋值

哈希赋值可以用一般的赋值语法来实现,不过使用更多的是利用胖箭头。

如果要用一般的赋值语法来赋值,例如:

my %new_hash = %old_hash;

在运行这行代码的时候,Perl程序会先将%old_hash展开为键-值对,然后通过列表赋值重新构建每一个键-值对,最终形成新的哈希%new_hash。

另一种赋值方法是利用胖箭头。本质上,这种赋值方法跟给数组赋值一样,只不过在给哈希赋值的时候,键与值是交替出现的,也就是说我们得从头开始计数,第奇数个为键,偶数个为值,这样赋值会非常麻烦,而且容易出错。胖箭头在Perl程序中是逗号的另一种写法,如果用胖箭头代替逗号,那么整个赋值过程会变得非常清晰明了,我们也可以一眼看出来谁是键谁是值。例如:

#正常的赋值方法
%some_hash = ('foo', 35, 'bar', 12.4, 2.5, 'hello', 'wilma', 1.72e30, 'betty', "bye\n");
#使用胖箭头赋值
%some_hash = (
    'fred' => 'flintstone',
    'dino' => undef,
    'barney' => 'rubble',
    'betty' => 'rubble',
);

不过胖箭头跟逗号还是有细微差别的,胖箭头左边的任意裸字都会自动加上引号,因此胖箭头左边的裸字不需要加引号。

哈希函数

Perl中有很多函数可以一次处理整个哈希。

keys函数和values函数

在列表上下文中,keys函数能返回哈希的键列表;values函数可以返回哈希的值列表。如果哈希表为空,那么这两个函数都会返回空列表。虽然哈希表中的元素的顺序是不可预测的,但是用这两个函数返回的键列表和值列表的顺序是能对应上的。只要在取得键与取得值这两个动作之间不修改哈希,那么顺序必然一致。在标量上下文中,这两个函数都会返回哈希中元素的个数。

each函数

如果需要迭代整个哈希,那么最快捷的方式就是用each函数。它会依次返回哈希中的键值对。如果所有的元素都被访问过,或者哈希表是空的,那么它就会返回空列表。在实战中,最常用到each的地方就是while循环,例如:

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

exists函数

如果要检查哈希表中是否存在某个键,可以使用exists函数,它的返回值是布尔变量,用来表示键值存在与否,而与键所对应的值无关。

delete函数

delete函数可以用来从哈希中删除指定的键及其相对应的值。假如没有这样的键的话,它就会直接结束且不会报错。例如:

my $person = "betty";
delete $books{$person};

reverse函数

这个函数会把哈希表展开成为键-值对列表,然后将键与值调换位置形成一个新列表,从而得到一个新的哈希表。这个函数只能在确保值也是唯一的时候使用,否则重复的值中,后面的会覆盖前面的,导致数据丢失。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值