哈希

哈希可以理解为查找表。你可以通过为每个内容指定密钥来访问其内容。键必须是字符串。如果他们不是,他们将被转换为字符串。

如果你给哈希只是一个已知的密钥,它将为你提供它的价值。

# Elements are in (key, value, key, value) sequence
my %inhabitants_of = ("London", 8674000, "Paris", 2244000);

# You can save some typing and gain in clarity by using the "fat comma"
# syntactical sugar. It behaves like a comma and quotes what's on the left.
my %translations_of_hello = (spanish => 'Hola', german => 'Hallo', swedish => 'Hej'); 

在下面的示例中,请注意括号和符号:使用 $hash{key} 访问%hash 的元素,因为你想要的是标量。一些人认为引用密钥是好习惯,而其他人认为这种风格在视觉上很嘈杂。只有那些可能被误认为像 $hash{'some-key'} 这样的表达的键才需要引用

my $greeting = $translations_of_hello{'spanish'};

虽然默认情况下 Perl 会尝试将裸字用作字符串,但+修饰符也可用于向 Perl 指示不应插入密钥,而是将执行结果用作密钥执行:

my %employee = ( name => 'John Doe', shift => 'night' );
# this example will print 'night'
print $employee{shift}; 

# but this one will execute [shift][1], extracting first element from @_,
# and use result as a key
print $employee{+shift};

与数组一样,你可以同时访问多个哈希元素。这称为哈希切片。结果值是一个列表,因此使用 @ sigil:

my @words = @translations_of_hello{'spanish', 'german'}; # ('Hola', 'Hallo')

使用 keys keys 迭代哈希的键将以随机顺序返回项目。如果你愿意,可以与 sort 结合使用。

for my $lang (sort keys %translations_of_hello) {
  say $translations_of_hello{$lang};
}

如果你实际上不需要像前面示例中那样的键,values 会直接返回哈希值:

for my $translation (values %translations_of_hello) {
  say $translation;
}

你还可以使用带有 each 的 while 循环来迭代哈希。这样,你将同时获得键和值,而无需单独的值查找。然而,它的使用是沮丧的,因为 each 可能会以错误的方式打破。

# DISCOURAGED
while (my ($lang, $translation) = each %translations_of_hello) {
  say $translation;
}

访问 unset 元素会返回 undef,而不是错误:

my $italian = $translations_of_hello{'italian'}; # undef

map 和 list flattening 可用于从数组中创建散列。这是创建一组值的常用方法,例如快速检查值是否在 @elems 中。此操作通常需要 O(n) 时间(即与元素数量成比例),但可以通过将列表转换为哈希值在恒定时间(O(1))内完成:

@elems = qw(x y x z t);
my %set = map { $_ => 1 } @elems;   # (x, 1, y, 1, t, 1)
my $y_membership = $set{'y'};       # 1
my $w_membership = $set{'w'};       # undef

这需要一些解释。@elems 的内容被读入列表,由 map 处理。map 接受为其输入列表的每个值调用的代码块; 元素的值可以在 $_ 中使用。我们的代码块为每个输入元素返回两个列表元素:$_,输入元素和 1,只是一些值。一旦你考虑了列表展平,结果是 map { $_ => 1 } @elemsqw(x y x z t) 变成了 (x => 1, y => 1, x => 1, z => 1, t => 1)

当这些元素被分配到散列中时,奇数元素变为散列键,偶数元素变为散列值。当在列表中多次指定密钥以分配给散列时,最后一个值获胜。这有效地丢弃了重复。

将列表转换为哈希的更快方法是使用对哈希切片的赋值。它使用 x 运算符将单元素列表 (1) 乘以 @elems 的大小,因此左侧切片中的每个键都有一个 1 值:

@elems = qw(x y x z t);
my %set;
@set{@elems} = (1) x @elems;

以下哈希应用程序还利用哈希和列表通常可以互换使用来实现命名函数 args 的事实:

sub hash_args {
  my %args = @_;
  my %defaults = (foo => 1, bar => 0);
  my %overrides = (__unsafe => 0);
  my %settings = (%defaults, %args, %overrides);
}

# This function can then be called like this:
hash_args(foo => 5, bar => 3); # (foo => 5, bar => 3, __unsafe ==> 0)
hash_args();                   # (foo => 1, bar => 0, __unsafe ==> 0)
hash_args(__unsafe => 1)       # (foo => 1, bar => 0, __unsafe ==> 0)

当用作布尔值时,如果它们不是空的,则为真。