perl列表和数组

1.数组元素引用

如果下标超出了数组的范围,则其值为undef。这和通常的变量情况是一样的,如果没有值存放在变量中,则其为undef。
$blank = $fred [142_857] #此数组元素未存放值,得到undef
$blanc = $mel; #$mel未存放值(未初始化),得到undef

 

特殊的数组索引

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

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

$rocks[1] =‘slate’; #又一个
$rocks[2] =‘lava’; #又一个
$rocks[3] =‘crushed rock’;#又一个
$rocks[99] =‘schist’; #现在有95个undef元素

有时需要知道数组最后一个元素的索引。刚才使用的rocks 数组,其最后一个元素的索引为$#rocks◆。这和数组中元素的
个数是不同的,因为数组中包含元素0。(换句话说,最后一个元素的索引值要比其实际包含的元素个数少一,译者注)。

$end = $#rocks; #99,最后一个元素的索引
$number_of_rocks = $end + 1; #正确,但有更好的方法
$rocks[$#rocks] =‘hard rock’; #the last rock

 

由于经常将$#name的值作为索引,像上面例子那样,因此,Larry提供了一种简便方法:数组的负数索引值从最后一个元
素开始。但不要认为这些索引是循环的。如果数组有3元素,那有效的负数索引值是-1(最后一个元素),-2(中间的元素),
-3(第一个元素)。实际上,几乎没有人使用除了-1之外的其它的负数索引值。
$rocks[-1] =‘hard rock’; #完成上例中的一种更简单的方法
$dead_rock =‘rocks[-100]’; #得到‘bedrock’,第0个元素
$rocks[-200] =‘crystal’; #严重错误(fatal error!)

 

2.列表

数组是由括号括起来并且其元素由逗号分隔开的列表。这些值组成了数组的元素:
(1,2,3) #含有1,2,3的列表
(1,2,3,) #同上,最后一个逗号被忽略
() #空列表-0个元素
(1..100)#包含100个整数的列表

最后一个例子使用了范围操作符(range operator)..,它创建了从左值到右值之间所有值的列表。
(1..5) #同(1,2,3,4,5)
(1.7..5.7) #同上—最小值和最大值被转换成整数
(5..1) #空列表—..中的左值应小于右值,否则为空
(0,2 .. 6,10,12)#同(0,2,3,4,5,6,10,12)
($m..$n) #由$m和$n的值决定
(0.. $#rocks) #上节中有$#rocks的介绍

当然,列表可以包含任意的标量值,如下面的包含字符串的例子:
(“fred”, “barney”, “betty”, “wilma”, “dino”)

实践表明,字符串的列表(如上例)在Perl中经常使用。有一种简便的方法可以不用输入大量的引号而达到类似的功能,
那就是使用qw。
qw(fred barney betty wilmadino ) #同上,但输入更少。

qw 表示“quoted words”或者“quoted by whitespace,”这依赖于你问的是谁。无论那种解释,Perl将它们当作单引号字符串
处理,你不能像双引号那样在qw中使用\n和$fred。whitespace(空格,像spaces,tabs,newlines等字符串)将被忽略,剩下
的组成了列表的元素。由于空格被忽略,所以下面(不常用的)是另一种书写方法:
qw(fred
barney betty
wilma dino) #同上,当看起来有些奇怪

前面两个例子是用括号作为分界符,但Perl允许使用任何标点符号作为分界符。下面是一些常用的类型:
qw ! fred barney betty wilma dino !
qw# fred barney betty wilma dino # #有些像注释
qw( fred barney betty wilma dino )
qw{ fred barney betty wilma dino }
qw[ fred barney betty wilma dino ]
qw< fred barney betty wilma dino >

qw!Yahoo\!Google excite lycos ! #其中一个元素为:字符串yahoo!

如我们处理Unix中的文件名:

qw{
/usr/dict/words
/home/rootbeer/.ispell_english
}

 

2.1 列表赋值

和标量值类似,列表值也可以赋给变量:
($fred, $barney, $dino) = (“flintstone”, “rubble”, undef);

在Perl中可以使用如下的简单方法交换两个变量的值◆:

($fred, $barney) =($barney, $fred) #交换两个变量
($betty[0],$betty[1]) = ($betty[1],$betty[0]);

如果变量个数(等号左边)不同于其值的个数(等号右边),将发生什么事情呢?在列表赋值中,额外的值会被自动忽略。
因为Perl认为,如果需要把值存起来,那应当指明其存储的地方。同样,如果有多余的变量,额外的变量被赋予undef◆。

($fred, $barney) = qw <flintstone rubble slate granite>; #两个值被忽略了
($wilma,$dino) = qw[flintstone]; #$dino 为undef

现在可以给列表赋值了,可以使用如下的一行代码来创建按一个字符串数组◆:

($rocks[0],$rocks[1],$rocks[2],$rocks[3])= qw/talc mica feldspar quartz/;

当想引用这个数组时,Perl有一种简单的写法。在数组名前加@(后没有中括号)来引用整个数组。你可以把他读作“all of the
(所有的)”,所以@rocks可以读作“all of the rocks(所有的石头)”◆。其在赋值运算符左右均有效:

@rocks = qw / bedrock slate lava /;
@tiny = (); #空表
@giant = 1..1e5; #包含100,000个元素的表
@stuff = (@giant, undef, @giant); #包含200,001个元素的表

@dino =“granite”;
@quarry = (@rocks,“crushed rock”, @tiny, $dino);

最后一个赋值语句将五个元素(bedrock, slate,lava, crushed rock, granite)赋给变量@quarry,因为@tiny没有元素。(特别的
是,它没有undef这个值,但可以像@stuff那样明确的指定它。)还有一点需要注意的是数组名字被其列表值替换。数组不
能成为列表的一个元素的原因是数组只能包含标量值,不能包含其它的数组◆。没有赋值的数组变量的值为( ),空表。和
未初始化的标量变量为undef类似,未被初始化的数组为空表。

 2.1.1pop 和push 操作

pop 操作将数组的最后一个元素取出并返回:
@array = 5..9;
$fred = pop(@array); #$fred 得到9,@array 现在为(5,6,7,8)
$barney = pop @array; #$barney gets 8, @array 现在为(5,6,7)
pop @array; #@array 现在为(5,6)(7 被丢弃了)

最后一个例子中,pop 使用在“in a void context”,也就是说没有存放其返回值的地方。这样使用pop 是合法的。

 如果数组为空,那pop 什么也不做(因为没有元素可以移出),并返回undef。

 你可能已注意到pop 后可以使用或者不使用括号。这在Perl 中是一条通用规则:如果去掉括号含义不变,那括号就是可选
的◆。和pop 相反的操作是push,它可以将一个元素(或者一列元素)加在数组的末尾:

push(@array,0); #@array 现在为(5,6,0)
push @array,8; #@array 现在为(5,6,0,8)
push @array,1..10; #@array 现在多了10 个元素
@others =qw/9 0 2 1 0 /;
push @array,@others; #@array 现在又多了5 个元素(共有19 个)


2.1.2shift 和unshift 操作

push 和pop 对数组的末尾进行操作(或者说数组右边有最大下标的元素,这依赖于你是怎样思考的)。相应的,unshift 和
shift 对一个数组的开头进行操作(数组的左端有最小下标的元素)。下面是一些例子:

@array = qw# dino fred barney #;
$m = shift (@array); #$m 得到“dino”, @array 现在为(“fred”, “barney”)
$n = shift @array; #$n 得到”fred”, @array 现在为(“barney”)
shift @array; #@array 现在为空
$o = shift @array; #$o 得到undef, @arry 仍为空
unshift(@array,5); #@array 现在为(5)
unshift @array,4; #@array 现在为(4,5)
@others = 1..3;
unshift @array, @others; #array 现在为(1,2,3,4,5)
和pop 类似,如果其数组变量为空,则返回undef。


3.将数组插入字符串

如果忘了数组插入的规则,当把email 地址插入双引号字符串时可能出现意想不到的结果。因此,“fred@bedrock.edu” 将表示email 地址。但当某人加入了一
个变量@bedrock;则这字符串将变成“fred.edu”或者更糟。

$email =“fred@bedrock.edu”; #错误!将会替换@bedrock
$email =“fred\@bedrock.edu”; #正确
$email =‘fred@bedrock.edu’; #另一种方法

只有一个元素的数组的被其值替换的行为和你预期的类似:
@fred = qw(hello dolly);
$y = 2;
$x =“This is $fred[1]’s place”; # “This is dolly’s place”
$x =“This is $fred[$y-1]’s place”; #同上



@fred = qw(eating rocks is wrong);
$fred = “right”; #我们将打印“this is right[3]”
print “this is $fred[3]\n”; #打印出“wrong”使用$fred[3]
print “this is ${fred}[3]\n”; #打印出“right”(由花括号分开)
print “this is $fred”. “[3]\n”; #正确(两个字符串,右. 分开)
print “this is $fred\[3]\n”; #正确(利用反斜线转义)



4.foreach 控制结构

foreach $rock (qw/ bedrock slate lava /){
print “One rock is $rock.\n”; #打印出3 种rocks
}

控制变量(本例中为$rock)每一次迭代从列表中取出一个新值。第一次为“bedrock”,第三次为“lava”。

控制变量不是这些列表元素中的一个拷贝而是这些元素本身。也就是说,如果在循环中修改这个变量,那原始列表中的元
素也会被修改
,如下面代码段所显示。这条性质是有用的,但是,如果不清楚,可能对其结果感到吃惊。

@rocks = qw/ bedrock slate lava /;
foreach $rocks(@rocks){
$rock = “\t$rock”; #@rocks 的每一个元素前加入一个tab
$rock . = “\n”; #每一个元素后加一个换行符
}
print “The rocks are:\n”,@rocks; #每一个元素都被缩进了,并且一个元素占一行

当循环结束时$rock 的值为多少呢?其值同循环开始之前相同。foreach 循环中控制变量的值会被Perl 自动保存和恢复。当
循环进行时,是没有办法改变其值的。循环结束时,变量的值会回到循环开始前,如果没有值则为undef。这意味着如果有
一个变量和控制变量有相同的名字:“$rock”,不用担心会混淆它们。

4.1Perl 最常用的默认变量:$_

如果在foreach 循环中省略了控制变量,那Perl 会使用其默认的变量:$_。除了其不寻常的名字外,这和普通变量类似,如
下面代码所示:
foreach(1..10){ #使用默认的变量$_
print “I can count to $_!\n”;
}

虽然它不是Perl 中唯一的默认变量,但无疑是使用的最普遍的。你将在许多例子中看到Perl 在没有要求它使用某个变量或
值时,会自动使用变量$_,这将节约程序员大量的时间来思考使用哪一个变量。为了消除你的疑虑,下面的print,就是使
用$_的一个例子:
$_ =“Yabba dabba doo\n”;
print; #打印出默认变量$_。


4.2reverse 操作

reverse(逆转)操作将输入的一串列表(可能是数组)按相反的顺序返回。如果不喜欢范围操作符: ..,只能从小到大,
那可以使用reverse 来解决这个问题:

@fred = 6 ..10;
@barney = reverse (@fred); #得到10,9,8,7,6
@wilma = reverse 6 ..10; #同上,没有使用额外的数组
@fred = reverse @fred; #将逆转过的字符串存回去

注意reverse 返回逆转的列表,它不会改变其参数的值。如果返回值没有赋值给某个变量,那这个操作是没有什么意义的:
reverse @fred; #错误,没有改变@fred 的值
@fred = reverse @fred; #改变了@fred 的值


4.3sort 操作

sort 操作将输入的一串列表(可能是数组)根据内部的字符顺序进行排序。如对于ASCII 字符串,将根据ASCII 序进行排
序。当然,ASCII 中有一些奇怪的地方,如大写字母在小写字符的前面,数字在字符的前面,而标点符号散布在各处。

@rocks = qw/ bedrock slate rubble granite /;
@sorted = sort(@rocks); #得到bedrock, granite, rubble, slate
@back = reverse sort @rocks; #为slate 到bedrock
@rocks = sort @rocks; #将排序的值写回@rocks
@numbers = sort 97 ..102; #得到100,101,102,97,98,99

从最后一个例子可以看到,如果将数字按照字符串进行排序可能得到没有意义的结果。当然,默认的排序规则下,任何由
1 开头的字符串先于由9 开头的字符串。


5.标量和列表上下文

可以毫不夸张地说,你的整个Perl 职业生涯都是建立在对本节的理解之上。

但这并非说本节难于理解。本节仅是一个简单的概念:一个给定的表达式在不同的上下文中其含义是不同的。这本身没什
么新奇的地方;事实上这在自然语言中是司空见怪的。例如,在英语中◆,假设某人问你“read”◆的含义。它的具体含义
和你怎样使用它有关。除非你知道它使用的上下文环境,否则不知道其确切的含义。

42 + something #something 必须是标量
sort something #something 必须是列表

@people = qw( fred barney betty );
@sorted = sort @people; #列表context:barney , betty, fred
$number = 42 + @people; #标量context:42+3,得到45

甚至普通的赋值(赋给标量或者列表)也产生不同的contexts:
@list = @people; #3 个People 的列表
$n = @people ; #数字3

5.1在标量Context 中使用List-Producing 表达式

有许多表达式通常都是产生列表的。当其在标量context 中使用时,会得到什么结果呢?让我们看看这个操作的创始人怎么
解释的。通常,这个人是Larry,其文档展现了整个历史。对于Perl 的学习,大部分是学习Larry 是怎么的想的◆。因此,
一旦你能像Larry 那样思考时,你就能明白Perl 的行为。当学习时,你可能需要查看其文档。

@backwards = reverse qw / yabba dabba doo /;
#返回doo, dabba, yabba
$backwards = reverse qw/ yabba dabba doo /;
#返回oodabbadabbay


$fred = something; # 标量context
@pebbles = something; #列表context
($wilma,$betty) = something; #列表context
($dino) = something; #列表context


5.2在列表Context 中使用Scalar-Producing 表达式

5.3强制转换为标量Context

偶尔,你可能需要标量context 而Perl 期望的是列表。这种情况下,可以使用函数scalar。它不是一个真实的函数因为其仅
是告诉Perl 提供一个标量context:

@rocks = qw(talc quartz jade obsidian);
print “How many rocks do you have?\n”;
print “I have ”, @rocks, “rocks!\n”; #错误,输出rocks 的名字
print “I have ”, scalar @rocks, “rocks!\n”; #正确,输出其数字




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值