rss· 投稿· 设为首页· 加入收藏· 繁體版
当前位置: 火魔网 » 程序开发 » Perl

Perl读书笔记-04

4 数组和哈希(hash) 4.1 数组和列表

    如果把标量看成是Perl的单数的话,那么列表(list)和数组可以认为是Perl中的复数。列表是标量的有序集。数组是包含列表的变量。严格意义上讲,列表是指数据,而数组是其变量名。

4.1.1 数组的初始化和元素引用

    列表是有序标量的集合,列表的每一个元素都是一个独立的标量,这些值是有顺序的。数组或者说列表中的元素是编了号的,其索引从整数0开始,依次递增一。

Perl中有三种变量,前面提到的标量变量的前缀($),而数组变量的前缀为(@),还有一种是哈希表的变量。

@tiny = (); #一个为空的数组。

@giant=1… 1e2 #包含从1到100,100个元素的数组

@stuff = (@giant,0,@gaint) #包含201个元素的数组

    数组是通过整数编号(索引)来访问数组元素的值,而且这些整数编号是连续的,访问数组元素的语法为:

$array_name[int_index]

如:

$jerry[0]=”abc”;

$jerry[1]=”def”;

$jerry[2]=2;

下面是Perl初始化和引用的例子:

#!perl

use strict;

my @arry1=();

$arry1[0]="abc";

$arry1[1]=1;

$arry1[2]="def";

@arry1=(@arry1,"hij");

foreach my $elem(@arry1){

    print("$elem, ");

#执行结果

abc, 1, def, hij,

    在C语言中访问数组有越界的问题,即下标超出了数组的范围。在Perl中,在访问超出数组范围的时侯,则其值为undef。没有初始化赋值的数组元素的值也为undef。

4.1.2 特殊的数组索引

    如果将一个元素存储在数组最后元素的后面位置,数组会自动增长。Perl没有长度的限制,只要你有足够的内存。

my @rocks = ();

$rocks[0]=’bedrock’ #一个元素

$rocks[1]=’slate’;又一个元素

$rocks[99]=’schist’; #数组@racks长度是100,有97个undef个元素。

    有时候需要知道数组最后一个元素的索引。例如上面的rocks数组,其最后一个元素的索引为$#rocks。这和数组中元素的个数不同,因为数组的索引从0开始,所以数组racks的元素个数为$#rocks+1。这样就有了其他语言中很常见的通过索引遍历数组的for循环:

my @rocks = ();

$rocks[0]='bedrock' ;

$rocks[1]='slate';

$rocks[2]='schist';

for(my $i=0;$i<=$#rocks;$i++){

    print($rocks[$i]." ");

#程序执行结果

bedrock slate schist

        Larry提供了数组负数索引值的访问元素方法,如果数组有3个元素,那么有效的负数索引是-1(最后一个元素),-2(中间的元素),-3(第一个元素)。

#!perl

use strict;

my @myarr1 = ();

$myarr1[0]='bedrock' ;

$myarr1[1]='slate';

$myarr1[2]='schist';

print($myarr1[-1]." "); # schist

print($myarr1[-2]." "); # slate

print($myarr1[-3]." "); #schist

if(!defined($myarr1[-4])){ #$myarr1[-4]的值为undef

    print($myarr1[-4]."undef");

#书中所说的严重错误(fatal error!)其实是指下面的初始化赋值操作

#$myarr1[-4]='aaa';

#Modification of non-creatable array value attempted, subscript -4 at p07.pl line 15.

4.1.3 数组的相关函数

        Perl提供了类似于栈一样的添加或者删除数组元素的函数pop和push。Pop函数将数组的最后一个元素取出并返回:

@arr1 = 5…9; #@arr1=5,6,7,8,9

$num = pop(@arr1); #$num变量的值为9,@arr1=5,6,7,8

pop(@arr1); #@arr1 为5,6,7

如果数组为空,那么pop什么也不做,并返回undef。

@arr1 = 5...9; #@arr1=5,6,7,8,9

while(@arr1){ #为空则@rr1返回undef, boolean判断undef(0,”” 都是false)为false

    print(pop(@arr1)." ");

#执行结果

9 8 7 6 5

push与pop操作正好相反,它可以将一个元素加到数组的末尾:

@arr1 = 5...9;

push(@arr1,0); #5,6,7,8,9,0

@arr2 = 10..12;

push(@arr1,@arr2); #5,6,7,8,9,0,10,11,12

        Push和pop对数组的末尾进行操作,相应的,unshift和shift对一个数组的开头进行操作。下面是一些例子:

@arr1 = 5…9; #@arr1=5,6,7,8,9

$num = shift(@arr1); #$num变量的值为5@arr1= 6,7,8,9

shift(@arr1); #@arr1 为7,8,9

unshift(@arr1,6); #@arr1 => 6,7,8,9

@arr2 = (4,5);

unshift(@arr1,@arr2); #arr1 => 4,5,6,7,8,9

        Perl还提供了一种不通过整数索引遍历数组的方法foreach,foreach从列表的第一个元素一直到最后一个元素,一次迭代一个,控制变量每次迭代都从列表中取出一个新值。

@arr1 = 5…9;

foreach $i(@arr1){

    Print(“$i ¥n”);

4.2 哈希(hash)

    哈希表是一种重要的数据结构。哈希表也被称为"关联数组(associative arrays)"。和数组一样,哈希表可以用来存储数据,和数组不同的是,其索引不是数字,而是一个唯一的字符串(称为key)。

    哈希表最大的特点是把数据的存储和查找消耗的时间大大降低,几乎可以看成是常数时间;而代价是消耗比较多的内存。目前的发展趋势来说,用空间换时间的做法是值得的。

4.2.1 Hash表的初始化和hash元素的引用

        Perl中有三种类型的变量,前面提到的标量变量前缀($),数组变量(@)。而哈希hash变量的前缀为(%). 初始化赋值的一般方法如下:

my %some_hash =(

    "key1"=>11.0,  

    "key2"=>"value2",

    "key3"=>"A\n"

);

    因为Perl是一种宽容的语言,下面的赋值的形式Perl也是允许的,但是推荐上一种更直观的初始化赋值的方法:

my %some_hash = (

  "name", "china",

  "age", 60

);

Hash表通过key来访问元素。要访问hash的元素(element),可以使用下面的语法:

$hash{$some_key}

    这和访问数组元素的方法有些类似,但是这里下标(key)上使用的是{},而不是[]。和数组一样,访问不存在的元素或者没有值的元素返回值为undef。

$family_name{"Xiang"}="Li";

$family_name{"小眼杰伦"}="周";

        Perl通过family_name前面的$和后面的{}判断其含义为hash元素,而不是标量变量什么的其他东西。所以hash表的初始化赋值也可以通过以下的方法:

C:\Users\LiXiang\Desktop\codes>more p18.pl

#!perl

use strict;

my %family_name=();

$family_name{"Xiang"}="Li";

$family_name{"小眼杰伦"}="周";

print("小眼杰伦的姓是: ".$family_name{"小眼杰伦"}."¥n");

C:\Users\LiXiang\Desktop\codes>perl p18.pl

小眼杰伦的姓是: 周

4.2.2. Hash函数

(a). keys和values函数

        keys函数会返回此hash的所有keys的列表,values函数将返回所有values的列表。如果hash中没有元素,则函数将返回空列表(undef):

my %some_hash=(

              "a"=>1,

              "b"=>2,

              "c"=>3

);

my @key=keys(%hash); 

my @val=values(%hash);

foreach my $it(@keys){

        print($it."\n");

[root@Ora01 codes]# perl p15.pl

有时候需要对一个哈希表是否为空用if做判断:

if(%some_hash){

  #%some_hash为空时为undef,undef在判断语句中为false。

(b). each函数

    如果想遍历一个哈希表中的所有元素,一种通常的方法是使用each函数,它将来返回key/value对的列表。当对同一个hash函数进行一次迭代时,将返回下一个key/value对,直到所有元素被访问则each函数将返回空表(false).

[root@Ora01 codes]# more p16.pl

#!/usr/bin/perl

use strict;

my %some_hash=(

        "a"=>1,

        "b"=>2,

        "c"=>3

);

while((my $key, my $value)=each(%some_hash)){

        print("Hash key: ".$key." Value: ".$value.".\n");

[root@Ora01 codes]# perl p16.pl

Hash key: c Value: 3.

Hash key: a Value: 1.

Hash key: b Value: 2.

    另一种遍历哈希表的办法是通过keys函数获取所有元素的keys列表,然后通过foreach和keys列表来访问values达到遍历的目的,上例的一个等效写法:

[root@Ora01 codes]# more p17.pl

#!/usr/bin/perl

use strict;

my %some_hash=(

        "a"=>1,

        "b"=>2,

        "c"=>3

);

foreach my $key(keys(%some_hash)){

        print("Hash key: ".$key." Value: ".$some_hash{$key}."\n");

[root@Ora01 codes]# perl p17.pl

Hash key: c Value: 3

Hash key: a Value: 1

Hash key: b Value: 2

[root@Ora01 codes]#

(c). exists函数

    要查看哈希表中是否存在某个key,可以通过使用exists函数,如果hash中存在此key,则返回true。

#!perl

use strict;

my %some_hash=(

        "a"=>1,

        "b"=>2,

        "c"=>3

);

my $b_key = "b";

if(exists($some_hash{$b_key})){

              print("hash \%some_hash exists key $b_key, and value :".$some_hash{"b"}."\n");

#执行运行结果

hash %some_hash exists key b, and value :2

(d). delete函数

        delete函数将摸个给定的key的元素从hash中删除,如果不存在这个key则什么都不做;不会有警告或者错误信息。

#!perl

use strict;

my %some_hash=(

        "a"=>1,

        "b"=>2,

        "c"=>3

);

delete($some_hash{"b"});

foreach my $key(keys(%some_hash)){

        print("Hash key: ".$key." Value: ".$some_hash{$key}."\n");

#执行结果

Hash key: c Value: 3

Hash key: a Value: 1

顶一下
(1)
踩一下
(0)