考虑以下perl脚本:
use strict;
use warnings;
use Data::Dumper;
# Expects an array reference and an undef replacement value
sub undef_to_value(\@$) {
my $array_ref = shift(@_);
my $default = shift(@_);
# Map each element in the array referenced by $array_ref to...
# If the element is defined, itself
# Otherwise, the $default value
return map {
defined($_) ? $_ : $default
} @{ $array_ref };
}
my %grades = ("Alice" => 100, "Bob" => 85, "Carol" => 92);
my @students = ("Alice", "Bob", "Eve");
以下代码按预期工作:
my @student_grades = @grades{ @students };
@student_grades = undef_to_value(@student_grades, 0);
print Dumper(\@student_grades);
# $VAR1 = [
# 100,
# 85,
# 0
# ];
但是,尝试传递哈希切片会导致Type of arg 1 to main::undef_to_value must be array (not hash slice)
:
my @student_grades = undef_to_value( @grades{ @students }, 0 );
如何将哈希切片同步到具有赋值的数组中,但在子例程调用期间不会? 有没有办法让失败的例子作为单一的任务工作?
答案 0 :(得分:4)
如何将哈希切片同步到具有赋值的数组
不是。列表上下文中的哈希切片评估为多个标量,列表赋值运算符对此非常满意。
换句话说,
@L{qw( a b )} = @R{qw( a b )};
相当于
($L{a}, $L{b}) = ($R{a}, $R{b});
正如您的评论所说,undef_to_value
需要数组引用。如果你提供一个数组,原型提供了这个,但你提供的是一个哈希切片。这不是一个变量类型,所以你不能引用它 [1] 。
只需接受标量:
sub undef_to_value {
my $default = shift(@_);
return map { $_ // $default } @_;
}
my @student_grades = undef_to_value(0, @grades{ @students });
当然,你可以简单地使用
my @student_grades = map { $_ // 0 } @grades{ @students };
\@h{LIST}
相当于map { \$_ } @h{LIST}
。答案 1 :(得分:0)
您可以通过引用然后取消引用任意列表来欺骗原型
undef_to_value( @{[@grades{ @students }]}, 0 );
但这只会修改输入的副本,因此没有用处。
undef_to_value( @{[@grades{ @students }]}, 0 );
print Dumper([@grades{@students}]);
---
$VAR1 = [
100,
85,
undef
];
幸运的是,您的undef_to_value
函数还会返回一组更新值,因此您可以说
@grades{@students} = undef_to_value( @{[@grades{ @students }]}, 0 );
print Dumper(\%grades);
---
$VAR1 = {
'Bob' => 85,
'Carol' => 92,
'Eve' => 0,
'Alice' => 100
};