Perl编程之路3
标签: perl
列表与数组
Perl里面代表复数的就是列表和数组
列表(list)指的是标量的有序集合, 而数组(array)则是存储列表的变量. 在Perl这两个属于尝尝混用, 不过更精确的是, 列表指的是数据, 而数组指的是变量, 列表的值不一定放在数组里, 但每个数组一定包含一个列表(即便是不含任何元素的空列表)
数组或列表中的每个元素, 都是单独的标量变量, 拥有独立的标量值, 从起始元素到终止元素的先后次序是固定的, 因为没个元素都是独立不相关的标量值, 所以列表或数组可能包含数字, 字符串, undef值或不同标量类型值的混合
数组和列表可以包含任意个元素, 最小是什么都没有, 最大则能填满整个内存
数组的名字空间和标量的名字空间是完全分开的, 你可以在同一个程序里再取一个相同名字的标量变量, Perl会将两者当成不同的东西 如图, 但是一定不要这么写!!!!!!!!
当然, 任何求值能得到的数字的表达式都可以用作下标, 假如他不是整数, 则会自动舍弃小数, 无论正负
1 $fred[0] = 1;
2 $fred[1] = 2;
3 $fred[2] = 3;
4 $number = 2.71828;
5 print $fred[$number - 1];
结果应该和print $fred[1]相同
假如超出数组的尾端, 则对应的值将会是undef。 这点和一般的标量相同, 如果从来没有对标量变量进行过赋值, 他的值就是undef
特殊的数组索引
假如你对索引值超过数组尾端的元素进行赋值, 数组将会根据需要自动扩大----只要有可用的内存分配Perl, 数组的长度是没有上限的. 如果在扩展过程中需要创建增补元素, 那么他们的默认取值为undef
$rocks[0] = 'bedrock'; #一个元素..
$rocks[1] = 'slate' ; #又一个...
$rocks[2] = 'lava'; #再来一个...
$rocks[3] = 'crushed rock'; #再来一个...
$rocks[99] = 'schist'; #现在有95个undef元素
取最后一个元素的值
$end= $#rocks; #99, 也就是最后一个元素的索引值
把$#name当成索引值得做法十分常见,所以Larry为我们提供了简写, 从数组尾端往回计数的"负数数组索引值".不过,超出数组大小的负数索引值是不会绕回来的. 假如你在数组中有3个元素, 则有效的负数索引值为-1(最后一个元素), -2(中间的元素), -3(第一个元素).如果你用-4或者再往后的索引值,只会得到undef而不会绕回到数组尾部.(在我理解的索引值,其实就是数组下标)
$rocks[-1] = 'hard rock' #相当于给最后一个数组元素赋值
列表直接量
列表直接量(listliteral, 也就是在程序代码中表示一列数据的写法), 可以由圆括号内用逗号隔开的一串数据表示, 而这些数据就称为列表元素, 如:
(1, 2, 3) #包含1, 2, 3这三个数字的列表
(1, 2, 3, ) #相同的三个数字(末尾逗号会被忽略)
("fred", 4.5) #两个元素, "fred"和4.5
() #空列表----0个元素
(1..100) #100个整数构成的列表
上面最后一行用到了..范围操作符, 该操作符会从左边的数字计数到右边, 每次加1, 以产生一连串的数字. 如:
(1.7..5.7) #范围是一到五 但是会被去掉小数部分
(5..1) #空列表, ..这个操作符只能向上计数
(0..$#rocks) #上节的rocks数组里的所有索引数字
数组中的蒜素不必都是常数---它们可以试表达式, 在每次用到这些直接量时都会被重新计算。
列表可以包含任何标量值, 像下面这个典型的字符串列表:
("fred", "barney", "betty", "whilma", "dino")
qw简写
在Perl程序里, 经常要建立简单的单词列表, 这时只需要使用简写, 就可以省去键入许多无谓引号的麻烦
qw(fred barney betty wilma dino) #同上, 但更简洁, 也更少击键
qw表示"quted word(加上引号的单词)" ,Perl会将其当成的单引号内的字符串来处理所以, 在qw构建的列表中, 不能像双引号内的字符串一样使用\n或$fred。 其中的空白符(如空格、制表符以及换行符)会被抛弃, 然后剩下的就是列表的元素。因为qw算是一种引用的形式, 所以不能将注释放在qw列表中。 有些人喜欢令每个元素单独成行, 这样就能排成一列, 查看和增删都很方便 如
qw(
fred
barney
betty
wilama
dino
)
前面两个例子是以一对园括号作为定界符(delimiter), 其实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( this as a \ read backslash);
列表的赋值
列表值可以被赋值给变量:
($fred, $barney, $dino) = ("123", "asd", "ert");
因为列表是子啊赋值运算开始之前建立的, 所以在Perl里互换两个变量的值相当容易:
($fred, $barney) = ($barney, $fred);#交换两个变量的值
($betty[0], $betty[1]) = ($$betty[1], $betty[0]);
对列表进行赋值时, 多出来的值会被悄悄忽略掉---Perl认为:如果你真的想将这些值存放起来的话, 你必然会告知存储位置。另一种情况, 如果变量的个数多过给定的列表值个数, 那么那些多出来的变量将会被设成undef
($fred, $barney) = qw<aaa eee ttt jjj>; #忽略掉末尾两个元素
($wilma, $dino) = qw[flints]; #$dino的值为undef
我们可以用如下代码来构建一个字符串数组:
($rocks[0], $rocks[1], $rocks[2], $rocks[3]) = qw/ aaa vvv dee ddgg/;
不过当你希望引用整个数组时, Perl提供了一个比较简单的记法。只要在数组名之前加上@字符就可以了。这种写法在赋值操作符两边都可以使用:
@rocks = qw/ ddd eee gggg /;
@tiny = ( ); #空列表
@giant = 1..1e5; #包含100 000个元素的列表
@stuff = (@giant, undef, @giant); #包含200 001个元素的列表
@$dino = "granite";
@quarry = (@rocks, "crushed rock", @tiny, $dino);
最后一行进行的赋值运算会将@quarry设成拥有5个元素的列表(ddd, eee, ggg , creshed rock, granite),因为@tiny贡献了0个元素给这个列表(由于空列表里没有任何元素, 也就不会有undef被赋值到列表中---但是如果需要undef我们也可以显式写明, 就像之前对@stuff的操作那样),此外, 值得注意的是 数组名会被展开成它所拥有的元素列表, 因为数组只能包含标量, 不能包含其他数组, 所以数组无法成为列表里的元素, 要留意的是,将某个数组复制到另一个数组时仍然算是列表的赋值运算,只不过这些列表是存储在数组里而已:
@copy = @quarry; #将一个数组中的列表复制到另一个数组
pop和push操作符
要新增元素到数组尾端时, 只要将它存放到更高的索引值对应的新位置就行了,不过不大用,数组中最右侧的便是最后一个元素, 也就是拥有最大索引的那个元素。因为我们常常要对这个元素进行操作, 所以Perl提供了专门的函数
pop操作符就是其中一个,它负责取出数组中最后一个元素并将其作为返回值返回
@array = 5..9;
$fred = pop(@array); # $fred 变成9, @array现在是(5,6,7,8)
$barney = pop @array; # barrey 现在变成8, @现在是(5,6,7)
pop @array # @array 现在是(5,6)。(7被抛弃了)
最后一行是在空上下文中使用pop,所谓的“空上下文”只不过是表示返回值无处可去的一种说辞。这其实也是pop操作符常见的一种用法, 用来删除数组中的最后一个 元素。
如果数组是空的,pop什么也不做,直接返回undef
pop后面加不加括号都可以, 这是Perl习惯之一, 只要不会因为拿掉括号而改变意愿,括号就是可省略的,push用于添加一个元素或者是一串元素到数组的尾端
push @array 1..10; #在array后面又添加了十个元素
@others = qw/ 9 0 2 1 0 /;
push @array, @others; #array又得到了5个新元素
注意,push的第一个参数或者pop的唯一参数都必须是操作的数组变量---对列表直接量进行压入或弹出操作是没有意义的
shift和unshift操作符
unshift和shift操作符浙式对数组的开头或者说左边最低下表部分进行相应的处理, 如:
@array = qw# dino fred barney #;
$m = shift(@array); # $m变成了 “dino”,@array现在是(“fred”, “barney”)
unshift(@array, 5); #array现在是5,“fred”, “barney”
splice操作符
splice操作符可以添加或者移除数组中间的某些元素,它最多可接受4个参数, 最后两个是可选参数, 第一个参数当然是要操作的目标数组, 第二个参数是要操作的以为元素的开始位置, 如果仅仅给出这两项参数, Perl会把从给定位置开始一直到末尾的全部元素取出来并返回
@array = qw(aaa bbb nnn ddd eee);
@removed = splice @array, 2; #在原来的数组中删掉fred及其后的元素
#@removed变成qw(nnn ddd eee);
#而原先的@array变成qw(aaa bbb)
我们可以通过第三个 参数指定要操作的元素长度,第三个参数表示要操作的元素个数。
@array = qw(aaa bbb ccc ddd eee);
@removed = splice @array, 1, 2; #删除bbb和ccc这两个元素
#@removed变成qw(bbb,ccc)
#而@array变成qw(aaa ddd eee)
第四个参数是要替换的列表,之前我们看到的都是如何从现有的数组拿走元素, 而其实你也可以补充新元素到原来的数组中。替换的列表长度并不一定要和拿走的元素片段一样长:
@array = qw(a b c d e);
@removed = splice @array, 1, 2, qw(wilma); #删除b 和 c
# @removed 变成qw(b c)
# @array 变成qw(a wilma d e)
实际上,添加元素列表并不需要预先删除某些元素, 把表示长度的第三个参数设为0,即可不加删除的插入新列表
@array = qw(a s d f g);
@removed = splice @array, 1, 0, qw(www);#什么元素都不删
# @removed 变为 qw()
#@array变为qw(a www s d f g)
注意,www出现在s之前的位置上。 Perl从索引位置1的地方插入新列表, 然后顺移原来的元素。