数组
数组中的每个元素都是单独的标量变量,并且是有序的,我们可以通过数组索引对其赋值
@array = ()
定义空数组,$#array
表示数组最后一次元素的索引值,$array[0]
表示数组第一个元素以及$array[-1]
表示数组最后一个元素等
怎么理解数组是有序这个意思呢,比如我想将有三个元素的数组赋值于一个只有两个元素的数组,那么后面的数组的第三个元素将自动被忽略,如下:
($one, $two) = ("aaa", "bbb", "ccc");
或者这么理解:
@array[2,3] = ("a", "bb");
对数组操作的话,有几个操作符:
push/pop操作符
push是将元素(或者数组)加到一个数组的尾端
push @array, 1; push @array, @tmp;
pop则相反,是取出数组中最后一个元素
pop @array; $a = pop @array;
shift/unshift操作符
这两个跟上面两个操作符相反,是处理数组开头的,比如shift是将数组的前一个元素取出
shift @array;
常与@ARGV搭配可一个个取出perl程序的输入参数
@file = shift @ARGV;
unshift则是跟shift相反操作,可将元素(或者数组)加到一个数组的开头
unshift @array, @tmp;
其实我觉得最好用的还是splice这个操作符,理论上行splice可以代替上面所有的操作符的功能,但是有些出于习惯和方便的原因,可能不会选择用splice代替
splice操作符可以接收4个参数,前两个是必须参数,后两个是可选参数。第一个参数当然是需要处理的数组@array,第二个参数为要操作的起始位置,第三个参数是操作的元素长度,第四个参数是要替换的列表(数组)。我们可以灵活使用这4个参数来对数组进行各种操作
splice ARRAY, OFFSET, LENGTH, LIST
对于splice的理解可以分为两部分,首先看是否赋值于新数组,比如下面两个代表着两个不同的意思
splice(@array, 2); @result = splice(@array, 2);
前者表示删除@array数组的第3个元素到最后一个元素,后者表示将@array的第3个元素到最后一个元素赋值于@result数组(当然,@array数组其实也发生了删除元素的步骤,切记!!)
接着可以按照splice操作符使用了几个参数来分不同的作用,比如删除第3个到第5个元素或删除第3个元素
splice(@array, 2, 3); splice(@array, 2, 1);
在数组第3个位置增加一个元素or数组
splice(@array, 3, 0, "add"); splice(@array, 3, 0, @add);
如果是替换元素呢,其实跟上述增加元素的用法是差不多的,比如用@repeat数组替换@array数组的第3到5个元素
splice(@array,2,3,@repeat);
还有以下几点需要注意的,下面这个表示返回最后一个移出的值,也就是返回@array数组的第5个元素
$result = splice(@array, 2, 3);
如果第三个参数为负数,那么第三个参数不再代表长度了,而是表示位置,如下表示移出第3个元素到最后一个元素
splice(@array, 2, -1);
如果第二个参数为负数,那么起始的位置不再是数组从头到尾了,而是从尾端的某个元素开始,如下表示移除数组@array最后2个元素
splice(@array, -2);
散列(哈希)
在Learning Perl这本书中称其为哈希,在Intermediate Perl这本书中则叫其为散列,当然其实我觉得还是散列更加贴切点,跟数组相对应嘛。散列是一种数据结构,能储存任意多的键以及其所对应的值,跟数组的的区别在于索引方式,散列是以"名字"来当做索引的,也称为键,键对应的储存数据则称为值。当然由于散列的键是字符串,所以在散列里面储存的数据是没有顺序的。不夸张的说,有散列的perl和没有散列的perl完全不是同一层次的语言。。。。个人觉得,因为其实在太好用了。。。。
散列中的键是必须唯一的,这跟数组的索引一样,%hash可以被这样赋值:
%hash = (key, value, key, value, key, value);
可以通过reverse
将%hash的键和值互换
%reverse_hash = reserve %hash;
其实一般是以胖箭头
%hash = (
a => "aaa",
b => "bbb",
);
可看到键没有给予引号,这是因为perl默认许可键如果是单纯的字符串是不同给引号的,比如
%hash{a} = 1;
但是不是单纯的字符串,而是表达式或者其他连接形式的话,则最好加引号,反正我徒省事,不然咋样都加引号,比如下面2个就是不同的键,前者键为aabb,后者键为aa.bb
%hash{aa.bb} = 1;
%hash{"aa.bb"} = 1;
如果想提取%hash的键和值,可以用keys函数和values函数,如果想对键排序则可再加上sort函数
@array = sort keys %hash; @array = values %hash;
当然如果想对每一对键-值进行处理,则可以使用each函数遍历散
列,而且其会记得每个上一次返回的是哪个键-值,所以其能迭代整个散列。但是如果散列重置(读取了所有元素,或者使用了keys %hash or values %hash)后,那么顺序会再次改变了
while(my ($k, $v) = each(%hash)){ print "$k => $v\n"; }
其实我也很少用each函数,因为如果是遍历整个散列,我会使用foreach搭配key函数,因人而异了
foreach (keys %hash){ print "$_ => $hash{$_}\n"; }
判断散列的键是否存在用exists函数,但我一般用if语句根据\(hash{\)key}对应的值是否为空来判断键$key是否存在,如下两个写法大部分时候是等价的
if (exists $hash{$key}){ print "xxx"; } if ($hash{$keys}){ print "xxx"; }
但是delete函数还是蛮有用的,可以删除特定的键,当然也顺便也删除了该键对应的值
delete $hash{$key};
切片
除了上述对数组和散列的操作外,还有一个比较重要的是切片,我喜欢用分割来理解,即将一个标量分割为一个数组,如下:
@array = split //;
上述默认的写法即是将$_变量按照每个字符进行分割,其实split在文件处理中,处理tab分割的每行数据更加好用
@array = split /\t/, $line;
其实perl对切片的定义是比较广的,下述这种也叫做切片
$array[0,1] = ($one, $two);
所以我们经常会看到这样的用法
($one, $two) = (split /\t/, $line)[0,1]
除了对数组进行切片,当然还有散列(哈希)的切片,我觉得这个非常强大!可惜总是忘记使用。。。
@array = @hash{@info}
那么要表达的就是提取出@info数组中的所有元素在%hash中作为键对应的值,并赋予数组@array;上述的复杂的写法则如下,两者的水平已经不是同一层次了。。。
foreach my $k (keys %hash) {
if (grep{$k eq $_}@info) {
push @array, $hash{$k};
}
}
本文出自于http://www.bioinfo-scrounger.com转载请注明出处