ind*_*ess 7 arrays perl hash undef map
任务:使用map构建哈希,其中keys是给定数组@a的元素,值是某些函数f($ element_of_a)返回的列表的第一个元素:
my @a = (1, 2, 3);
my %h = map {$_ => (f($_))[0]} @a;
Run Code Online (Sandbox Code Playgroud)
好的,直到f()返回一个空列表(对f()来说绝对正确,在这种情况下我想分配undef).可以使用以下代码重现该错误:
my %h = map {$_ => ()[0]} @a;
Run Code Online (Sandbox Code Playgroud)
错误本身听起来像"散列分配中奇数个元素".当我重写代码时:
my @a = (1, 2, 3);
my $s = ()[0];
my %h = map {$_ => $s} @a;
Run Code Online (Sandbox Code Playgroud)
要么
my @a = (1, 2, 3);
my %h = map {$_ => undef} @a;
Run Code Online (Sandbox Code Playgroud)
Perl根本没有抱怨.
那么我该如何解决这个问题 - 当返回的列表为空时,获取f()返回的列表的第一个元素?
Perl版本是5.12.3
谢谢.
我刚刚玩了一下,似乎()[0]在列表上下文中,它被解释为空列表而不是undef标量.例如,这个:
my @arr = ()[0];
my $size = @arr;
print "$size\n";
Run Code Online (Sandbox Code Playgroud)
打印0.所以$_ => ()[0]大致相当于$_.
要修复它,您可以使用该scalar函数强制标量上下文:
my %h = map {$_ => scalar((f($_))[0])} @a;
Run Code Online (Sandbox Code Playgroud)
或者您可以undef在列表的末尾附加一个明确的:
my %h = map {$_ => (f($_), undef)[0]} @a;
Run Code Online (Sandbox Code Playgroud)
或者你可以将函数的返回值包装在一个真正的数组中(而不仅仅是一个平面列表):
my %h = map {$_ => [f($_)]->[0]} @a;
Run Code Online (Sandbox Code Playgroud)
(我个人最喜欢最后一个选项.)
在"切片"perldata下的"切片"下记录了一个空列表切片的特殊行为:
一个空列表的片仍然是一个空列表.[...]这使得编写在返回空列表时终止的循环变得容易:
Run Code Online (Sandbox Code Playgroud)while ( ($home, $user) = (getpwent)[7,0]) { printf "%-8s %s\n", $user, $home; }