Perl 数据结构学习笔记
Perl 脚本常用数据结构的学习总结用于以后自己参考,包括数组、散列、散列的数组、数组的散列、混合结构的使用,参考资料:Perl数据结构,Perl 教程
数组,二维数组(数组的数组)
一个数组的创建和索引
my @a = ("abc", "abc", "abc") ;
my $size = @a; # 数组大小
my $tmp = $a[0]; # 数组索引
my @queue;
push @queue, \@a; # 二维数组
print " $queue[0][0]"; # 二维数组索引
需要注意的是,二维数组其实就是一个放置每个一维数组引用(指针)的一维数组,所以在给二维数组添加元素的时候,push的是一个一维数组的引用
push @queue, \@a; # 二维数组
那么索引这个二维数组的写法也就好理解了,引用 “ \ ” 这个概念先mark下,方便后续理解更复杂的数据结构,对于不用类型的数据结构可以用 $, @, %来解引用。
print " $queue[0][0]"; # 二维数组索引
类似的,多维数组的创建和索引也就好理解了
my @queue3;
push @queue3, \@queue;
print "$queue3[0][0][0]\n";
请记住在每一对相邻的花括弧或方括弧之间有隐含的 ->,因此下面三行是等价的。
$AoA[2][3]
$ref_to_AoA->[2][3]
$ref_to_AoA->[2]->[3]
{ } 或 [ ] 之间的 -> 是可省略的。但下面这种情况要注意,虽然之前我们使用 $queue[0][0] 的写法省略了->,但是我们需要清楚 $_内存放的仍是一个一维数组的引用,解析时不能忽略 ->。
for(@queue){
print "$_->[0]\n";
}
数组作为传参
Perl 支持函数之间的传参是一个标量,或者是一个数组。当然这个数组可以是二维数组,包含多个数组的引用,那就可以传更多参数了。
my @getPara;
my @givePara = ("aa","bb","cc");
@getPara = testSub(@givePara);
print "my getPara[0]: $getPara[0]";
sub testSub{
my @input = @_;
print "my input[0]: $input[0]\n";
my @output = ("11", "22", "33");
return @output;
}
下面是利用多维数组传递多组传参的例子,这里我们将 @givePara1, @givePara2 的引用放在 @givePara 中作为传参给子函数。
$input[0] 存放的是 @givePara1 的引用,因此需要通过解引用将参数传递给@input1
$input2是另一种方法,继承 @givePara2 的引用,在索引的时候通过 ->来解引用
my @getPara;
my @givePara1 = ("aa","bb","cc");
my @givePara2 = ("dd","ee","ff");
my @givePara = (\@givePara1,\@givePara2);
@getPara = testSub(@givePara);
@getPara1 = @{$getPara[0]};
@getPara2 = @{$getPara[1]};
print "my getPara[0][0]: $getPara[0][0]\n";
print "my getPara1[0]: $getPara1[0]\n";
print "my getPara2[0]: $getPara2[0]\n";
sub testSub{
my @input = @_;
my @input1,$input2;
@input1 = @{$input[0]};
$input2 = $input[1];
print "my input[1][0]: $input[1][0]\n";
print "my input1[0]: $input1[0]\n";
print "my input2[0]: $input2->[0]\n";
my @output1 = ("11", "22", "33");
my @output2 = ("44", "55", "66");
my @output = (\@output1,\@output2);
return @output;
}
散列,也叫哈希
哈希的创建和索引
哈希是很多条记录键字(key)与值(val)一一对应组合的集合,一个哈希的创建和索引是这样的:
my $a = 18, $b = 180, $c = 150;
$str = "xiaoming";
my %student = (
"name" => $str, # key => val,键字的 " " 也可以忽略
"age" => $a,
"high" => $b,
"weight" => $c
);
print "$student{'name'}\n";
新增记录,可以直接加,索引键字的 “” ''也是可以忽略的
PS:hash里面的记录是乱序的哦
my $scr = 99;
$student{score} = $scr;
print "$student{score}\n";
哈希作为传参
函数之间传递哈希的时候,Perl是将它放到数组 @_ 里面传递的,下面程序可以看出来:
my $a = 18, $b = 180, $c = 150;
$str = "xiaoming";
my %student = (
name => $str,
"age" => $a,
"high" => $b,
"weight" => $c
);
testSub();
sub testSub{
my @input = @_;
for (@input) {
print "$_\n";
}
}
它的打印结果是这样的:(哈希是乱序的)
high
180
name
xiaoming
age
18
weight
150
不过也是可以直接将结果赋值到哈希中的
my $a = 18, $b = 180, $c = 150;
$str = "xiaoming";
my %student = (
name => $str,
"age" => $a,
"high" => $b,
"weight" => $c
);
my %getStu = testSub(%student);
foreach my $key (keys %getStu) {
my $val = $getStu{$key};
print "$key : $val\n";
}
sub testSub{
my %inputHash = @_;
foreach my $key (keys %inputHash) {
my $val = $inputHash{$key};
print "$key : $val\n";
}
print "----------------\n";
my $aa = 19, $bb = 181, $cc = 151;
$strr = "xiaoming";
my %student = (
name => $strr,
"age" => $aa,
"high" => $bb,
"weight" => $cc
);
return %student;
}
当然,也可以传递哈希的引用,再通过 % 解引用。
my $a = 18, $b = 180, $c = 150;
$str = "xiaoming";
my %student = (
name => $str,
"age" => $a,
"high" => $b,
"weight" => $c
);
my $getStuTmp = testSub(%student); #### <----------
my %getStu = %{$getStuTmp}; #### <----------
foreach my $key (keys %getStu) {
my $val = $getStu{$key};
print "$key : $val\n";
}
sub testSub{
my %inputHash = @_;
foreach my $key (keys %inputHash) {
my $val = $inputHash{$key};
print "$key : $val\n";
}
print "----------------\n";
my $aa = 19, $bb = 181, $cc = 151;
$strr = "xiaoming";
my %student = (
name => $strr,
"age" => $aa,
"high" => $bb,
"weight" => $cc
);
return \%student; #### <----------
}
这里有点麻烦,但是要传递多个哈希表就有思路了,搞一个哈希的数组就可以了。
哈希的数组
一个哈希数组的创建和索引
my $a = 18, $b = 180, $c = 150;
$str = "xiaoming";
my %student = ( name => $str,age => $a,high => $b,weight => $c );
my @class = (
{ name => $str,age => $a,high => $b,weight => $c },
{ name => $str,age => $a,high => $b,weight => $c }
);
for my $x (0..5){
$str = $str.$x; $a = $a + 1; $b = $b + 1; $c = $c + 1;
my %tmpStu = ( name => $str,age => $a,high => $b,weight => $c );
push @class,\%tmpStu;
}
print " ---> $class[3]{name}\n";
哈希数组作为传参
与数组作为传参的使用类似,注意索引,其他不再赘述。
数组的哈希
创建一个数组的哈希以及索引数组元素
一个数组的哈希,键字对应的值是数组的引用,在添加数组哈希或者索引数组元素的时候注意引用与解引用的区分
my %class = (
person => ["xiaoming","xiaogang","xiaohua"],
age => ["11","12","13"],
high => ["120","130","140","150"]
);
my @a = ("60","70","80","90");
$class{weight} = \@a;
print "$class{age}->[2]\n";
数组的哈希作为传参
与哈希作为传参的使用类似,注意索引,其他不再赘述。
哈希的哈希
与数组的哈希类似,键字对应的值是的哈希引用,注意引用
my %student1 = ( person => "xiaoming", age => "11", high => "120" );
my %student2 = ( person => "xiaogang", age => "12", high => "130" );
my %student3 = ( person => "xiaohua" , age => "13", high => "140" );
my %class = (
monitor => \%student1,
commissary1 => \%student2
);
$class{commissary2} = \%student3;
print "$class{monitor}->{person}\n";
函数的哈希
9.5 函数的散列
在使用 Perl 书写一个复杂的应用或者网络服务的时候,你可能需要给你的用户制作一大堆命令供他们使用。这样的程序可能有象下面这样的代码来检查用户的选择,然后采取相应的动作:
if ($cmd =~ /^exit$/i) { exit }
elsif ($cmd =~ /^help$/i) { show_help() }
elsif ($cmd =~ /^watch$/i) { $watch = 1 }
elsif ($cmd =~ /^mail$/i) { mail_msg($msg) }
elsif ($cmd =~ /^edit$/i) { $edited++; editmsg($msg); }
elsif ($cmd =~ /^delete$/i) { confirm_kill() }
else {
warn "Unknown command: `$cmd'; Try `help' next time\n";
}
你还可以在你的数据结构里保存指向函数的引用,就象你可以存储指向数组或者散列的引用一样:
%HoF = ( # Compose a hash of functions
exit => sub { exit },
help => \&show_help,
watch => sub { $watch = 1 },
mail => sub { mail_msg($msg) },
edit => sub { $edited++; editmsg($msg); },
delete => \&confirm_kill,
);
if ($HoF{lc $cmd}) { $HoF{lc $cmd}->() } # Call function
else { warn "Unknown command: `$cmd'; Try `help' next time\n" }
在倒数第二行里,我们检查了声明的命令名字(小写)是否在我们的“遣送表”%HoF 里存在。如果是,我们调用响应的命令,方法是把散列值当作一个函数进行解引用并且给该函数传递一个空的参数列表。我们也可以用
&{ $HoF{lc $cmd} }( ) 对散列值进行解引用,或者,在 Perl 5.6 里,可以简单地是 $HoF{lc $cmd}
()。
混合数据结构的使用
Perl 程序中还有可能用到数组、哈希等数据结构的混合数据结构,这种也可以将其合并为一个混合结构
my $testStr = "I am a string";
my @test = ("aa","bb","cc");
my $a = 18, $b = 180, $c = 150;
my $str = "xiaoming";
my %student = ( name => $str,age => $a,high => $b,weight => $c );
my @class = (
{ name => $str."_1",age => $a,high => $b,weight => $c},
{ name => $str."_2",age => $a,high => $b,weight => $c}
);
my %school = (
person => ["xiaoming_3","xiaogang","xiaohua"],
age => ["11","12","13"],
high => ["120","130","140","150"]
);
my $rec = {
STR => $testStr,
QUE => \@test,
HASH => \%student,
HASHQUE => \@class,
QUEHASH => \%school
};
$rec->{STRADD} = $str;
print "string try : $rec->{STR} \n";
print "queue try : $rec->{QUE}->[0]\n";
print "hash try : $rec->{HASH}->{name}\n";
print "hashque try : $rec->{HASHQUE}->[0]{name}\n";
print "quehash try : $rec->{QUEHASH}->{person}[0]\n";
print "stringadd try : $rec->{STRADD} \n";
注意混合结构 $rec 定义取值使用的是 { } ,它是整个混合结构的引用,所以可以看到后边索引内部元素的时候都要先用 -> 解引用(划重点)
好了,以上就是这次全部的学习内容了,函数哈希没实际用到,有遇到的话下次补充~