hash基本用法

Perl中hash类型的变量使用%前缀表示,由列表创建而成,列表的格式为(k1,v1,k2,v2,k3,v3),即按照一个键一个值的方式构建hash。

例如,构建一个名为person的hash变量:

my %person = (
  "name"  , "junmajinlong",
  "age"   , 23,
  "gender", "male"
);

Perl中,几乎总是可以使用=>代替逗号。因此,下面是等价的方式:

my %person = (
  "name"  => "junmajinlong",
  "age"   => 23,
  "gender"=> "male"
);

当key的名称符合标识符命名规范时(只包含下划线、字母和数值,且非数值开头),可以省略key的引号。因此,构建hash时通常写成下面这种可读性更高的方式:

my %person = (
  name   => "junmajinlong",
  age    => 23,
  gender => "male"
);

可以根据$hash{key}的方式来检索hash结构中key对应的value,如果key符合标识符命名规范,则可以省略包围key的引号。

my %person = (
  name   => "junmajinlong",
  age    => 23,
  gender => "male"
);

say "$person{name}";
say $person{"age"};

如果访问hash中不存在的key,则返回undef,而不会报错:

say $person{class};  # undef

hash变量不能内插到双引号。

say "%person";   # 直接输出:%person

在列表上下文,hash变量会自动隐式转换为(k1,v1,k2,v2,k3,v3)格式的列表

my %person = (
  name   => "junmajinlong",
  age    => 23,
  gender => "male"
);

# hash展开成列表,默认所有的key和value紧密相连输出
# 修改内置变量`$,`可设置say/print输出时的列表分隔符
say %person;  # namejunmajinlonggendermaleage23
$, = "-";
say %person;  # name-junmajinlong-gender-male-age-23

在标量上下文,如果hash为空,则转换为数值0,如果hash结构非空,则hash变量会转换为m/n格式的标量,m表示当前的键值对数量,n表示hash结构当前的容量。因此,可以直接将hash变量作为布尔值判断:非空hash为true、空hash为false。

my %h;     # 空hash
say ~~%h;  # 输出:0
if(%h){say "empty hash"}  # 不输出

$h{k1} = "v1";
say ~~%h;   # 输出:1/8
if(%h){say "not empty hash"}  # 输出

将hash变量赋值给另一个hash变量时,由于赋值hash时在列表上下文,因此会先将hash展开为列表,再赋值。

my %person = (
  name   => "junmajinlong",
  age    => 23,
  gender => "male"
);

my %p = %person;  # %person展开为列表,然后构建%p

多键组合的hash

在向hash中存储数据时,如果想要用多份数据组合起来作为key,那么可以用字符串相连的方式将它们的值连接起来:

my %h;
my ($x, $y) = qw(x, y);
$h{$x.$y} = "junmajinlong.com";  # 等价于$h{"$x$y"}
say $h{"$x$y"};

但这样的方式不安全。例如$x=aa,$y=aa组合作为key时,和使用$a=a,$b=aaa组合作为key是一样的。

Perl提供了一种更简便、更安全的逗号分隔,方式,当使用逗号分隔多份数据组合为key时,Perl会自动将每份数据使用下标连接符(默认值为\034)连接起来,最终得到的字符串作为key。\034通常可以认为是安全的连接符,它是一个ASCII中的控制字符,几乎不会出现在文本数据中。

my %h;
my ($x, $y) = qw(x y);

$h{$x, $y, "name"} = "junmajinlong.com";
say $h{$x, $y, "name"};
say $h{"$x\034$y\034name"};  # 等价形式

Perl使用的下标连接符由内置变量$;控制,该内置变量的默认值为\034。因此,下面这种写法也和上面的写法等价。

say $h{join($;, $x, $y, "name")};