最初,我正在使用长度= 2 ^ 16的列表。但是,为了抽象这个,我将在这个例子中设置length = 5。
#subroutine to make undefined entries -> 0
sub zeros {
foreach(@_) {
if(!defined($_)) {
$_ = 0;
}
}
}
#print out and indicies and elements of list
sub checking {
print "List = \n";
my $counter = 0;
foreach (@_) {
print "index = $counter\n";
print "$_\n";
$counter += 1;
}
print "\n";
}
方法1 :如果我访问不同的索引来编辑元素,我打印出数组时会得到以下内容。 我不想看到空白。我希望他们为0 。我已经设置了一个子程序“零”来使未定义的条目变为零。但我不知道我的代码出了什么问题。我还为列表的每个元素尝试了“$ _ + = 0”。我仍然无法为空条目获取零。
#method 1
@abc = ();
$abc[1] = 3;
$abc[5] = 5;
&zeros(@abc);
&checking(@abc);
List =
index = 0
index = 1
3
index = 2
index = 3
index = 4
index = 5
5
方法2 :如果我像这样初始化列表,我可以得到零。但正如我所说,我正在处理很长的列表,我不能绝对不会像这样初始化我的列表。
#method 2
@abc = (3,0,0,0,5);
&checking(@abc);
List =
index = 0
3
index = 1
0
index = 2
0
index = 3
0
index = 4
5
答案 0 :(得分:4)
您可以使用
初始化您的列表吗?@abc = (0) x 2**16
将其设置为2 ** 16个零的列表?
我尝试使用你的零方法。如果我像这样初始化数组:
@abc = (undef, 1, undef, undef, undef, 5)
所以看起来子例程不会替换不存在的数组条目(与现有条件相反,但值为undef
)
在这种情况下,您可以尝试扩展zeros
子例程以返回修改后的数组并将其分配回原始数组:
#subroutine to make undefined entries -> 0
sub zeros {
foreach(@_) {
if(!defined($_)) {
$_ = 0;
}
}
return @_;
}
@abc = ();
$abc[1] = 3;
$abc[5] = 5;
@abc = zeros(@abc);
# Check:
print "index = $_\n$abc[$_]\n" for 0..$#abc;
或者,您可以传递对原始数组的引用:
#subroutine to make undefined entries -> 0
sub zeroref {
my ($array) = @_; # Expect a single argument: An array-reference
foreach(@$array) {
if(!defined($_)) {
$_ = 0;
}
}
}
@abc = ();
$abc[1] = 3;
$abc[5] = 5;
zeroref(\@abc); # Pass an array-reference instead
# Check:
print "index = $_\n$abc[$_]\n" for 0..$#abc;
答案 1 :(得分:4)
您的方法是正确的,但您的zeros()
功能存在问题。您使用@abc
作为参数调用它,该参数生成该列表的副本。然后,您更改副本。在sub的末尾,该副本被丢弃。在checking()
功能中,您仍在使用原始列表。
你可以这样解决:
sub zeros {
my @list = @_;
@list = map { $_ // 0 } @list;
return @list;
}
@abc = zeros(@abc);
checking(@abc);
诀窍是返回修改后的列表并将其重新分配给原始变量。
如果您使用过strict
和warnings
,那么它就会告诉您:
Use of uninitialized value $_ in concatenation (.) or string at F:\scratch.pl line 28. List = index = 0
index = 1 3 index = 2
index = 3
index = 4
index = 5 5
Use of uninitialized value $_ in concatenation (.) or string at F:\scratch.pl line 28.
Use of uninitialized value $_ in concatenation (.) or string at F:\scratch.pl line 28.
Use of uninitialized value $_ in concatenation (.) or string at F:\scratch.pl line 28.
但是由于你正在处理一个非常大的数组,我建议使用数组引用,因为复制会很昂贵。
sub zeros {
$_ //= 0 for @{ $_[0] };
}
zeros(\@abc);
checking(@abc);
答案 2 :(得分:1)
use 5.010;
$_ //= 0 for @abc;
对于5.10之前的perls,
$_ = defined($_) ? $_ : 0 for @abc;
如果您想将其转换为函数,请不要返回值,因为替换是就地的:
use 5.014;
use strict;
use warnings;
use YAML;
my @abc;
$abc[1] = 3;
$abc[5] = 5;
print Dump \@abc;
map_undefined_entries_to_zeros(\@abc);
print Dump \@abc;
sub map_undefined_entries_to_zeros {
my $array_ref = shift;
$_ = defined($_) ? $_ : 0 for @$array_ref;
return;
}
答案 3 :(得分:1)
如果你更喜欢懒惰或按需用零替换undef元素,你可以tie
这样的数组:
package Ad::Hoc::UndefToZero;
use Tie::Array;
our @ISA = qw(Tie::StdArray);
sub FETCH {
my ($tied, $i) = @_;
my $elt = $tied->SUPER::FETCH($i);
unless (defined $elt) {
$elt = 0;
$tied->STORE($i, $elt); # $tiedarray[$i] is now zero
}
$elt;
}
package main;
tie my @abc, 'Ad::Hoc::UndefToZero';
$abc[1] = 3;
$abc[5] = 5;
print "$abc[0]\n"; # $abc[0] now set to zero