Perl语言哈希的运用

  • 什么是哈希?
    哈希是一种数据结构,它和数组的相似之处在于可以容纳任意多的值并能按需取用,而它和数组的不同在于索引方式,数组是以数字来索引,哈希则以名字来索引。也就是说,哈希的索引值,此处称为键( key ),并不是数字、而是任意唯一的字符串。
    键总会被转换为字符串
    哈希的值可以是数字、字符串、undef,或是这些类型的组合。
    哈希的键则必须全部是唯一的字符串。

  • 为何使用哈希?
    事实上只要问题中带有"找出重复"、“唯一”、“交叉引用”、"查表"之类的字眼,实现时就很有可能会用到哈希。

  • 访问哈希元素 $hash{$some_key}

(1)在挑选哈希名的时候,最好使得哈希名和键之间能放进去一个 “for” 字。
比如"family_name for fred是flintstone",因此把哈希命名为family_name能清晰地反映出键和值之间的关系。

my %family_name;
$family_name{'fred'} = 'flintstone';
$family_name{'barney'} = 'rubble';
foreach my $person (qw< fred barney>){
        print "I've heard of $person $family_name{$person}.\n";
}

在这里插入图片描述

(2)哈希键可以是任意的表达式:

$foo = 'bar';
print "barney => $family_name{ $foo . 'ney'}";

在这里插入图片描述

(3)若对某个已存在的哈希元素赋值,就会覆盖之前的值:

$family_name{'fred'} = 'astaire';
print "fred => $family_name{'fred'}.\n";

在这里插入图片描述

(4)哈希元素会因赋值而诞生:

$family_name{'wilma'} = 'flintstone';
$family_name{'betty'} = $family_name{'barney'};
my @family_name = %family_name;
print "@family_name\n";

在这里插入图片描述

(5)访问哈希表里不存在的值会得到 undef

  • 访问整个哈希
    要指代整个哈希,可以用百分号( % )作为前缀。
    哈希可以转换为列表,反之亦然。对哈希赋值时,列表中的元素应该为键-值对;展开(unwinding)哈希时,即将哈希变成键-值对列表,得到的键-值对不一定是按照当初赋值时的顺序展开。因此选择使用哈希的场合,要么元素存储顺序无关紧要,要么可以容易地在元素输出时进行排序。当然,即使键-值对的顺序被打乱,列表里的每个键还是会"黏着"相应的值。
my %some_hash;
%some_hash = ('foo',35,'bar',12.4,2.5,'hello','wilma',1.72e30,'betty',"bye\n");
my @any_array = %some_hash;
print "@any_array\n";

在这里插入图片描述

  • 哈希赋值
    (1)用一般的赋值语法来复制哈希:my %new_hash = %some_hash;
    (2)建立一个反序的哈希:my %inverse_hash = reverse %any_hash;
    只能在哈希值不重复的情况下使用,否则就会导致重复的键。

  • 胖箭头
    对Perl而言,=>是逗号的另一种写法,即在任何需要逗号( , )的地方都可以用胖箭头( => )代替。
    胖箭头左边的任何裸宇(一连串的字母、数字和下划线,但不得以数字开头)都会自动加上引号,因此胖箭头左边的裸字不需要加引号。
    另外,在作为哈希键使用时如果花括号内只有裸字时,则两边的引号也可以省略。

my %last_name = (
        'fred' => 'flintstone' ,
        'dino' => undef ,
        'barney' => 'rubble' ,
        'betty' => 'rubble',    #请注意,列表结尾有一个额外的逗号,这种写法不但无伤大雅,而且便于维护。
);

my %last_name = (
        fred => 'flintstone' ,
        dino => undef ,
        barney => 'rubble' ,
        betty => 'rubble',
);  #使用胖箭头的时候可以省略键的引号,左边的部分会被自动引起
    #当然,也不是所有情况都可以这么做,因为哈希的键可以是任意形式的字符串,
    #所以要是某个键的内容含有Perl的操作符,就会偏离我们的预想甚至编译出错
  • 哈希函数
  • keysvalues 函数

(1)keys 函数能返回哈希的键列表,而values 函数能返回对应的值列表。如果哈希没有任何成员,则两个函数都返回空列表。只要在取得键与取得值这两个动作之间不修改哈希,则返回的键列表和值列表的顺序是一致的。

my @k = keys %some_hash;
my @v = values %some_hash;

(2)在标量上下文中,这两个函数都会返回哈希中元素(键-值对)的个数。

my $count1 = keys %some_hash;
my $count2 = values %some_hash;

print "k = @k\n" .
"v = @v\n" .
"count1 = $count1\n" .
"count2 = $count2\n";

(3)把哈希当成布尔表达式来判断真假(少见):只要哈希中至少有一个键-值对,就返回真

if (%some_hash) {
        print "That was a true value! \n" ;
}else{
        print "That was a false value! \n" ;
}

在这里插入图片描述
在这里插入图片描述

  • each函数(该函数的详细运行过程请看书本 P125 )

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

while ( ($key,$value) = each %some_hash ){
        printf "%10s => %-10s\n",$key,$value;
}

在这里插入图片描述

(2)假如你需要依次处理哈希,只要对键排序就行了。方法如下所示:

foreach $key (sort keys %some_hash) {
        printf "%10s => %-10s\n",$key,$some_hash{$key};
}

在这里插入图片描述

  • 哈希的典型应用

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

  • delete 函数
    delete 函数能从哈希中删除指定的键及其相对应的值。假如没有这样的键,它就会直接结束,而不会出现任何警告或错误信息。

  • 哈希元素内插
    可以将单一哈希元素内插到双引号引起的字符串中,就和你想要的一样:(但这种方式不支持内插整个哈希)

my %some_hash = (
        fred => 'flintstone' ,
        dino => undef ,
        barney => 'rubble' ,
        betty => 'rubble',
        july => '0',
);
foreach $key (sort keys %some_hash) {
        if ($some_hash{$key}) { #两种判断,两种结果,看截图
        #if (exists $some_hash{$key}) {
                print "$key has $some_hash{$key} items\n";
        }
}

在这里插入图片描述

  • %ENV 哈希
    访问Perl程序外的任意环境变量
    print "PWD is $ENV{PWD}\n";
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值