博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Perl匿名数组、hash和autovivification特性
阅读量:6803 次
发布时间:2019-06-26

本文共 5227 字,大约阅读时间需要 17 分钟。

可有构建匿名的对象,这样就没必要去为只用一两次的数组、hash去取名字,有时候取名是很烦的事。

  • 使用中括号[]构建匿名数组
  • 使用大括号{}构建匿名hash
  • 不包含任何元素的[]{}分别是匿名空数组、匿名空hash

构造匿名对象

例如,在数组、hash中构建匿名数组:

@name=('fairy',['longshuai','wugui','xiaofang']);%hash=('longshuai' => ['male',18,'jiangxi'],        'wugui'     => ['male',20,'zhejiang'],        'xiaofang'  => ['female',19,'fujian'],       );say "$name[1]";          # 输出ARRAY(0x...)say "$hash{wugui}";      # 输出ARRAY(0x...)say "$name[1][2]";say "$hash{wugui}[1]";

如果不想在匿名数组中输入引号,可以使用qw()。

# 以下等价@name=('fairy',['longshuai','wugui','xiaofang']);@name=('fairy',[qw(longshuai wugui xiaofang)]);

在数组、hash中构建匿名hash:

@name=(         # 匿名hash作为数组的元素       {    # 第一个匿名hash        'name'=>'longshuai',        'age'=>18,        'prov'=>'jiangxi',       },       {    # 第二个匿名hash        'name'=>'wugui',        'age'=>20,        'prov'=>'zhejiang',       },       {    # 第三个匿名hash        'name'=>'xiaofang',        'age'=>19,        'prov'=>'fujian',       },      );%hash=(          # 匿名hash作为hash的value        'longshuai'=>{   # 第一个匿名hash                      'gender'=>'male',                      'age'   =>18,                      'prov'  =>'jiangxi',                     },        'wugui'=>{    # 第二个匿名hash                  'gender'=>'male',                  'age'   =>20,                  'prov'  =>'zhejiang',                 },        'xiaofang'=>{    # 第三个匿名hash                     'gender'=>'female',                     'age'   =>19,                     'prov'  =>'fujian',                    },      );say "$name[2]";       # 输出HASH(0x...)say "$hash[wugui]";   # 输出HASH(0x...)say "$name[2]{age}";say "$hash{wugui}{prov}";

再例如,将一个匿名hash赋值给一个引用变量:

$ref_myhash = {               name => 'Gilligan',               hat => 'White',               shirt => 'Red',               position => 'First Mate',              };

为了后期维护方便,匿名数组、匿名hash中最后一个元素都使用了逗号。这个逗号并不会影响结果,但是却给未来修改匿名对象带来很大方便。

解除匿名对象的引用

从上面实验的结果中可以看到,当输出匿名对象时,其实输出的是个引用。

say "$name[1]";       # 输出ARRAY(0x...)say "$hash{wugui}";   # 输出ARRAY(0x...)say "$name[2]";       # 输出HASH(0x...)say "$hash[wugui]";   # 输出HASH(0x...)

既然是引用,就可以解除引用,还原到数据对象:

  • 正常情况下,使用@{数组引用}的方式解除数组引用,使用%{hash引用}的方式解除hash引用
  • 所以使用@{匿名数组}解除匿名数组,使用%{匿名hash}解除匿名hash
  • 注意,解除正常的数组、hash引用时,可以使用非规范的解除方式(去掉大括号,如@$ref_name),但是解除匿名对象的引用,必须不能去掉大括号
  • 访问匿名对象中的元素和正常对象一样。一般没有必要去获取匿名对象中的元素,但是却有必要设置匿名对象中的元素时,后面介绍autovivification时将会看到这种行为

例如,解除匿名数组对象,并获取匿名数组中的元素:

say "@{ ['longshuai','xiaofang','wugui'] }";   # 解除匿名对象的引用say "@{ [qw(longshuai xiaofang wugui)] }";     # 解除匿名对象的引用say "@{ [qw(longshuai xiaofang wugui)] }[1]";  # 获取匿名对象中的第二个元素

解除匿名hash对象,并获取匿名hash中的元素:

$ref_hash={   # 构造匿名hash,赋值给引用变量           'longshuai'=> ['male',18,'jiangxi'],           'wugui'    => ['male',20,'zhejiang'],           'xiaofang' => ['female',19,'fujian'],                };@mykeys=keys %{ $ref_hash };  # 通过引用还原到匿名hashsay "@mykeys";                # 输出匿名hash中的键say $ref_hash->{wugui}[2];    # 输出匿名hash中匿名数组的某个元素

再例如,直接在需要hash的地方构建一个匿名hash,并解除引用。

@mykeys=keys %{   # 解除匿名hash                 { # 构造匿名hash                  'longshuai'=> ['male',18,'jiangxi'],                  'wugui'    => ['male',20,'zhejiang'],                  'xiaofang' => ['female',19,'fujian'],                 }               };say %{   # 解除匿名hash       { # 构造匿名hash        'longshuai'=> ['male',18,'jiangxi'],        'wugui'    => ['male',20,'zhejiang'],        'xiaofang' => ['female',19,'fujian'],             },     };

如何区分匿名hash和一次性代码块

匿名hash使用大括号进行构建。但除了匿名hash,大括号还可以用来包围一堆语句,作为只执行一次的语句块。例如:

{    my $name="longshuai";    my $prov="jiangxi";}# 出了语句块,上面两个my标记的变量就失效了

那么如何让perl知道大括号是用来构造匿名hash的,还是用来做一次性语句块的?大多数时候,Perl根据上下文的环境会自动判断出来,但是有些时候无法判断,这时可以显式告诉Perl,这是匿名hash的构造符号,还是一次性语句块的符号。

  • 大括号前面加上+符号,即+{...},表示这个大括号是用来构造匿名hash的
  • 大括号内部第一个语句前,多使用一个;,即{;...},表示这个大括号是一次性语句块

+还可以加在匿名数组的中括号前,以及hash引用变量、数组引用变量前,而不仅仅是匿名hash的大括号前,如+$ref_hash+[]+$ref_arr

@{ +[qw(longshuai wugui)]}   # 匿名数组中括号前@{ +$ref_arr }           # 数组引用变量前%{ +$ref_hash }          # hash引用变量前

Perl的autovivification特性

这个单词,真的无语了,竟然找不到对应的翻译,是perl自造的词,但却应用到了多种语言中:。

根据它的功能,我将其大概解释下:当解除引用时,如果解除目标不存在,perl会自动创建一个空目标,而且自动创建时,会自动递归补齐上层。注意,是解除引用时。

这就像unix下的mkdir命令的-p选项一样,当创建某个目录的时候,如果它的父目录不存在,就会自动创建。

例如,下面的示例:

#!/usr/bin/perluse 5.010;push @{ $config{path} },'/usr/bin/perl';say keys %config;        # 输出:pathsay $config{path};       # 输出:ARRAY(0x...)say $config{path}[0];    # 输出:/usr/bin/perl

执行到push的时候,perl首先会发现@{}在解除一个引用,这个引用是$config{path},是一个hash引用,但是perl发现这个hash不存在,hash里的key(即path)也不存在,而且既然是push操作,说明这个key对应的value是个列表。于是perl的autovivification特性,首先会构建一个空的hash对象%config={},然后创建hash里的一个key:path,其值为空列表,即$config{path}=[],最后将"/usr/bin/perl"这个字符串push到对应的列表中,即$config{path}=['/usr/bin/perl']

在上面的示例中,perl在解除引用时,自建了几个层次:1.自建一个hash对象;2.自建hash对象中的一个元素;3.自建hash对象中某个元素的value部分。

必须注意,perl的autovivification功能只在解除引用的时候才自建,从解除引用的操作动机上看,当要解除引用,说明可能要操作引用对象中的数据了,那么缺少的部分应该要补齐。

如果不是在解除引用,那么perl将根据语法特性决定是否自建对象。例如下面将自建数组@name和hash对象%person以及它的一个元素$person{name}。但这不是autovivification的特性,而是perl的语法特性。

push @name,"longshuai";$person{name}="longshuai"say "$name[0]";say keys %person;

紧跟着上面的示例:

@{ $config{path} }[2]='/usr/bin/perl';say $config{path};       # 输出:ARRAY(0x5571664403c0)say $config{path}[0];    # 输出:空say $config{path}[1];    # 输出:空say $config{path}[2];    # 输出:/usr/bin/perlsay scalar @{$config{path}};   # 输出元素个数:3

转载地址:http://itjwl.baihongyu.com/

你可能感兴趣的文章
Java分享笔记:泛型类的定义与使用
查看>>
springCloud全实战超详细代码demo+笔记
查看>>
Golang 知识点总结
查看>>
Bitmap
查看>>
(转)arcgis面状文件坐标导出方法
查看>>
LPC824 周立功AM824学习笔记
查看>>
SQL数据库学习之路(三)
查看>>
开发https应用
查看>>
js轮换广告
查看>>
墨菲定律
查看>>
Maven
查看>>
MovieReview—Kingsman THE SECRET SERVICE(王牌特工之特工学院)
查看>>
C语言成长学习题(九)
查看>>
银行里的迷宫
查看>>
codevs——1294 全排列
查看>>
9.13模拟试题
查看>>
自动生成单据编号
查看>>
[noip模拟]画展<队列的基础知识>
查看>>
Java时间转换类实现
查看>>
ios之UITextfield (2)
查看>>