如何在perl中将列表元素复制到散列键?

qq24tv8q  于 2022-11-24  发布在  Perl
关注(0)|答案(4)|浏览(137)

我已经找到了几种方法来将列表中的元素复制到散列的键中,但是有人能解释一下这是如何工作的吗?

#!/usr/bin/perl
use v5.34.0;

my @arry = qw( ray bill lois shirly missy hank );

my %hash;
$hash{$_}++ for @arry;  # What is happening here?

foreach (keys %hash) {
  say "$_ => " . $hash{$_};
}

输出是我所期望的。我不知道任务是如何完成的。

hank => 1
shirly => 1
missy => 1
bill => 1
lois => 1
ray => 1
nue99wik

nue99wik1#

$hash{$_}++ for @array;

也可以写

for (@array) {
    $hash{$_}++;
}

或者更明确地说

for my $key (@array) {
    $hash{$key}++;
}

$_是“默认的输入和模式搜索空间”变量。通常在Perl函数中,你可以省略显式变量的命名,默认使用$_for就是一个例子。你也可以写一个显式变量名,这可能会让你的代码更有信息性:

for my $word (@words)

或者用成语来说:

for my $key (keys %hash)    # using $key variable name for hash keys

您还应该知道forforeach在Perl中是完全相同的。它们是同一个函数的别名。因此,我总是使用for,因为它更短。
代码的第二部分 * 是 * 赋值,使用自动递增运算符++
它被附加到LHS上的变量,并以1为增量增加其值。例如:

$_++           means $_ = $_ + 1
$hash{$_}++    means $hash{$_} = $hash{$_} + 1
...etc

它还包含了一个Perl魔法,你可以在文档中阅读更多。在这种情况下,这意味着它甚至可以递增未定义的变量而不发出警告。这在初始化哈希键时是理想的,因为它事先并不存在。
你的代码将为@arry列表中的每个单词初始化一个哈希键,并计算每个单词的出现次数。在本例中,它恰好是1。这是需要指出的,因为哈希键是唯一的,你的数组列表可能比哈希中的键列表大,因为一些键会相互覆盖。

my @words = qw(foo bar bar baaz);
my %hash1;

for my $key (@words) {
    $hash{$key} = 1;       # initialize each word
}

# %hash1 = ( foo => 1, bar => 1, baaz => 1 );
#                      note -^^

my %hash2;    # new hash
for my $key (@words) {
    $hash{$key}++;         # use auto-increment: words are counted
}

# %hash2 = ( foo => 1, bar => 2, baaz => 1);    
#                      note -^^
6qqygrtg

6qqygrtg2#

这里还有一个

my %hash = map { $_ => 1 } @ary;

说明:map每次取输入数组的一个元素,并为每个元素准备一个列表,这里有两个--元素本身($_,因为=〉也被引用)和一个1。这样的对列表然后填充一个散列,因为可以为一个散列分配一个偶数长度的列表,从而每两个连续的元素形成一个键值对。
注意:这并不考虑数组中相同元素可能多次出现的情况,而只是构建一个存在性检查结构(无论元素是否在数组中)。

hgb9j2n6

hgb9j2n63#

$hash{$_}++表示@数组;这里发生了什么?
它在数组中迭代,对于每个元素,它将其作为一个键分配给哈希,并将该键的值递增1。你也可以这样写:

my %hash;
my @array = (1, 2, 2, 3);

for my $element (@array) {
    $hash{$element}++;
}

结果将是:

$VAR1 = {
          '2' => 2,
          '1' => 1,
          '3' => 1
        };
bvuwiixz

bvuwiixz4#

$hash{$_}++ for @arry;  # What is happening here?

读取perlsyn,特别是简单语句和语句修饰符:

简单语句

简单语句的唯一类型是一个表达式,它会评估它的副作用。每个简单语句都必须以分号结束,除非它是块中的最后一个语句,在这种情况下分号是可选的。但是如果块占用了不止一行,无论如何都要把分号放在里面,因为你最终可能会添加另一行。注意,有一些运算符,如eval {}sub {}、和do {},它们看起来像复合语句,但实际上不是--它们只是表达式中的TERMs--因此在用作语句中的最后一项时需要显式终止。

语句修饰符

任何简单的陈述式都可以选择性地在结尾分号(或区块结尾)之前加上 SINGLE 修饰词。可能的修饰词有:

if EXPR
unless EXPR
while EXPR
until EXPR
for LIST
foreach LIST
when EXPR

[...]
for(each)修饰符是一个迭代器:它对LIST中的每一项执行一次语句($_依次别名为每一项)。

print "Hello $_!\n" for qw(world Dolly nurse);

相关问题