如何将列表元素复制到 perl 中的散列键?
How do I copy list elements to hash keys in perl?
我找到了几种将列表元素复制到散列键的方法,但有人可以解释一下这是如何工作的吗?
#!/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
$hash{$_}++ for @arry; # What is happening here?
它遍历数组,对于每个元素,它都将其分配为散列的键,并将该键的值递增 1。你也可以这样写:
my %hash;
my @array = (1, 2, 2, 3);
for my $element (@array) {
$hash{$element}++;
}
结果将是:
$VAR1 = {
'2' => 2,
'1' => 1,
'3' => 1
};
这是另一个
my %hash = map { $_ => 1 } @ary;
解释:map takes an element of the input array at a time and for each prepapres a list, here of two -- the element itself ($_
, also quoted because of =>) 和 1
。这样的对列表然后填充散列,因为可以将偶数长度的列表分配给散列,由此每两个连续元素形成一个 key-value 对。
注意:这不考虑数组中相同元素可能多次出现的情况,而只是构建一个 existance-check 结构(无论元素是否在数组中)。
$hash{$_}++ for @arry; # What is happening here?
阅读perlsyn, specifically simple statements and statement modifiers:
简单语句
唯一一种简单语句是为其 side-effects 求值的表达式。每个简单语句都必须以分号结束,除非它是块中的最后一个语句,在这种情况下分号是可选的。但是,如果该块占用多于一行,无论如何都要加上分号,因为您最终可能会添加另一行。请注意,像 eval {}
、sub {}
和 do {}
这样的运算符看起来像复合语句,但实际上不是——它们只是表达式中的术语——因此需要一个当用作语句中的最后一项时显式终止。
语句修饰符
任何简单的语句都可以选择在终止分号(或块结束)之前跟一个 SINGLE 修饰符。可能的修饰符是:
if EXPR
unless EXPR
while EXPR
until EXPR
for LIST
foreach LIST
when EXPR
[...]
for(each)
修饰符是一个迭代器:它对 LIST 中的每个项目执行一次语句($_
依次为每个项目别名)。在这种形式中没有语法来指定 C-style for 循环或词法范围内的迭代变量。
print "Hello $_!\n" for qw(world Dolly nurse);
$hash{$_}++ for @array;
也可以这样写
for (@array) {
$hash{$_}++;
}
或更明确地说
for my $key (@array) {
$hash{$key}++;
}
$_
是“默认输入和 pattern-searching space”-变量。通常在 Perl 函数中,您可以省略命名要使用的显式变量,它默认使用 $_
。 for
就是一个例子。您还可以编写一个明确的变量名,这可能会为您的代码提供更多信息:
for my $word (@words)
或惯用语:
for my $key (keys %hash) # using $key variable name for hash keys
您还应该知道 for
和 foreach
在 Perl 中完全相同。它们是同一功能的别名。因此,我总是使用 for
因为它更短。
代码的第二部分是赋值,使用了auto-increment operator ++
它被附加到 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 -^^
我找到了几种将列表元素复制到散列键的方法,但有人可以解释一下这是如何工作的吗?
#!/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
$hash{$_}++ for @arry; # What is happening here?
它遍历数组,对于每个元素,它都将其分配为散列的键,并将该键的值递增 1。你也可以这样写:
my %hash;
my @array = (1, 2, 2, 3);
for my $element (@array) {
$hash{$element}++;
}
结果将是:
$VAR1 = {
'2' => 2,
'1' => 1,
'3' => 1
};
这是另一个
my %hash = map { $_ => 1 } @ary;
解释:map takes an element of the input array at a time and for each prepapres a list, here of two -- the element itself ($_
, also quoted because of =>) 和 1
。这样的对列表然后填充散列,因为可以将偶数长度的列表分配给散列,由此每两个连续元素形成一个 key-value 对。
注意:这不考虑数组中相同元素可能多次出现的情况,而只是构建一个 existance-check 结构(无论元素是否在数组中)。
$hash{$_}++ for @arry; # What is happening here?
阅读perlsyn, specifically simple statements and statement modifiers:
简单语句
唯一一种简单语句是为其 side-effects 求值的表达式。每个简单语句都必须以分号结束,除非它是块中的最后一个语句,在这种情况下分号是可选的。但是,如果该块占用多于一行,无论如何都要加上分号,因为您最终可能会添加另一行。请注意,像 eval {}
、sub {}
和 do {}
这样的运算符看起来像复合语句,但实际上不是——它们只是表达式中的术语——因此需要一个当用作语句中的最后一项时显式终止。
语句修饰符
任何简单的语句都可以选择在终止分号(或块结束)之前跟一个 SINGLE 修饰符。可能的修饰符是:
if EXPR
unless EXPR
while EXPR
until EXPR
for LIST
foreach LIST
when EXPR
[...]
for(each)
修饰符是一个迭代器:它对 LIST 中的每个项目执行一次语句($_
依次为每个项目别名)。在这种形式中没有语法来指定 C-style for 循环或词法范围内的迭代变量。
print "Hello $_!\n" for qw(world Dolly nurse);
$hash{$_}++ for @array;
也可以这样写
for (@array) {
$hash{$_}++;
}
或更明确地说
for my $key (@array) {
$hash{$key}++;
}
$_
是“默认输入和 pattern-searching space”-变量。通常在 Perl 函数中,您可以省略命名要使用的显式变量,它默认使用 $_
。 for
就是一个例子。您还可以编写一个明确的变量名,这可能会为您的代码提供更多信息:
for my $word (@words)
或惯用语:
for my $key (keys %hash) # using $key variable name for hash keys
您还应该知道 for
和 foreach
在 Perl 中完全相同。它们是同一功能的别名。因此,我总是使用 for
因为它更短。
代码的第二部分是赋值,使用了auto-increment operator ++
它被附加到 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 -^^