可有构建匿名的对象,这样就没必要去为只用一两次的数组、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 }; # 通过引用还原到匿名hash
say "@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自造的词,但却应用到了多种语言中:Wiki Autovivification

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

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

例如,下面的示例:

#!/usr/bin/perl
use 5.010; push @{ $config{path} },'/usr/bin/perl'; say keys %config; # 输出:path
say $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/perl
say scalar @{$config{path}}; # 输出元素个数:3

Perl匿名数组、hash和autovivification特性的更多相关文章

  1. Perl 引用与匿名数组

    写这篇是因为工作遇到一个需要使用列表作为hash的值的问题,这在Python中是非常简单而轻松的事,如下面这段python程序. def add_to_index(index, keyword, ur ...

  2. Perl Learning 5 Hash

    [本文原创,未经同意请勿转载] 哈希是一种数据结构,它和数组的相似之处在于能够容纳随意多的值并能按需取用,而它和数组的不同在于索引方式,数组是以数字来索引.哈希则以名字来索引.也就是说.哈希的索引值, ...

  3. Java SE学习之数组——匿名数组和不规则数组

    本文是学习网络上的文章时的总结以及自己的一点实践.感谢大家无私的分享. 近期偶然遇到了数组的问题,学习了匿名数组和不规则数组. 匿名数组适用于仅仅使用一次的情况:不规则数组适用是每行数据总数不确定的情 ...

  4. Perl关联数组用法集锦

    本文和大家重点讨论一下Perl关联数组的概念,创建Perl关联数组,从数组变量复制到Perl关联数组,元素的增删,用Perl关联数组循环等内容,相信通过本文的学习你对Perl关联数组的用法一定会有深刻 ...

  5. bzoj 1669: [Usaco2006 Oct]Hungry Cows饥饿的奶牛【dp+树状数组+hash】

    最长上升子序列.虽然数据可以直接n方但是另写了个nlogn的 转移:f[i]=max(f[j]+1)(a[j]<a[i]) O(n^2) #include<iostream> #in ...

  6. PHP数组/Hash表的实现/操作、PHP变量内核实现、PHP常量内核实现 - [ PHP内核学习 ]

    catalogue . PHP Hash表 . PHP数组定义 . PHP变量实现 . PHP常量实现 1. PHP Hash表 0x1: 基本概念 哈希表在实践中使用的非常广泛,例如编译器通常会维护 ...

  7. perl 判断数组相等的三种方法

    1.数组相等,数组成员相同,位置也相同 一般的如果判断@array1 等于 @array2 a.数组长度相同 $#array1=$#array2, 比较数组长度,不能使用length函数,length ...

  8. Perl中的hash类型

    hash类型 hash类型也称为字典.关联数组.映射(map)等等,其实它们都是同一种东西:键值对.每一个Key对应一个Value. hash会将key/value散列后,按序放进hash桶.散列后的 ...

  9. [Perl] 删除数组中重复元素

    写一个小程序时候,需要去除一个数组中的重复元素,搜索了一下,找到的代码主要是两种,一种是使用grep函数,一种是转换为hash表,代码分别如下: 使用grep函数代码片段:代码: my @array ...

随机推荐

  1. 【翻译】从头开始写一个时间序列数据库-Writing a Time Series Database from Scratch

    本文来自: https://fabxc.org/tsdb/, 如翻译有误,请纠正. 我是从事监控工作的.特别是Prometheus, 一个包含自定义的时间序列库以及集成Kuberntes的监控系统. ...

  2. 背水一战 Windows 10 (99) - 关联启动: 关联指定的文件类型, 关联指定的协议

    [源码下载] 背水一战 Windows 10 (99) - 关联启动: 关联指定的文件类型, 关联指定的协议 作者:webabcd 介绍背水一战 Windows 10 之 关联启动 关联指定的文件类型 ...

  3. Java面试题总结(附答案)

    1.什么是B/S架构?C/S架构? B/S(Browser/Server),浏览器/服务器程序: C/S(Client/Server),客户端/服务端,桌面应用程序. 2.网络协议有哪些? HTTP: ...

  4. IM系统的MQ消息中间件选型:Kafka还是RabbitMQ?

    1.前言 在IM这种讲究高并发.高消息吞吐的互联网场景下,MQ消息中间件是个很重要的基础设施,它在IM系统的服务端架构中担当消息中转.消息削峰.消息交换异步化等等角色,当然MQ消息中间件的作用远不止于 ...

  5. 关于Python打开IDLE出现错误的解决办法

    安装好python,打开IDLE出现以下错误: 解决办法: 修改[Python目录]\Lib\idlelib\PyShell.py文件,在1300行附近,将def main():函数下面use_sub ...

  6. 使用CSS样式的三种方式

    外部样式表 当样式需要被应用到很多页面的时候,外部样式表将是理想的选择.使用外部样式表,你就可以通过更改一个文件来改变整个站点的外观. 内部样式表 当单个文件需要特别样式时,就可以使用内部样式表.你可 ...

  7. 性能瓶颈之System

    如果Source,Target,Mapping和Session都不存在性能上的瓶颈,则问题可能会出在System 因为Integration Service运行时,它使用了System的资源去运行组件 ...

  8. os模块及其API&属性

    模块: os os.path 所包含API列表: os.uname: 获取详细的系统信息 os.rename: 文件重命名 os.remove: 删掉文件 os.mkdir: 创建一个目录 os.rm ...

  9. c++多继承多态

    C++多继承多态的实现 如果一个类中存在虚函数,在声明类的对象时,编译器就会给该对象生成一个虚函数指针,该虚函数指针指向该类对应的虚函数表. 多态的实现是因为使用了一种动态绑定的机制,在编译期间不确定 ...

  10. tensorflow 迭代周期长,每个epoch时间变慢

    理论上,session启动后,每个epoch训练时间应该是差不多,而且不会因为迭代周期变长,epoch时间变慢.原因是session里定义了tf.op导致的,每一次迭代都会在graph里增加新的节点, ...