如何在Perl中获得一个列表来显示空条目的零?
最初,我正在处理一个长度为2^16的列表。然而,为了抽象这一点,我将在本例中设置length=5如何在Perl中获得一个列表来显示空条目的零?,perl,Perl,最初,我正在处理一个长度为2^16的列表。然而,为了抽象这一点,我将在本例中设置length=5 #subroutine to make undefined entries -> 0 sub zeros { foreach(@_) { if(!defined($_)) { $_ = 0; } } } #print out and indicies and elements of list
#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。我已经设置了一个子例程“zeros”,使未定义的条目变为零。但是我不知道我的代码出了什么问题。我还为列表的每个元素尝试了“$+=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
你能用电脑初始化你的名单吗
@abc = (0) x 2**16
哪个选项将其设置为2**16个零的列表
我试过用你的零方法。如果我像这样初始化数组,它会起作用:
@abc = (undef, 1, undef, undef, undef, 5)
sub zeros {
my @list = @_;
@list = map { $_ // 0 } @list;
return @list;
}
@abc = zeros(@abc);
checking(@abc);
因此,子例程似乎不会替换不存在的数组项(与现有的数组项相反,但其值为unde
)
在这种情况下,您可以尝试扩展零
子例程以返回修改后的数组并将其分配回原始数组:
#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;
或者,您可以传递对原始数组的引用:
#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;
您的方法是正确的,但是
zeros()
函数存在问题。您使用@abc
作为参数调用它,它将复制该列表。然后更改副本。在子对象的末尾,该副本将被丢弃。在checking()
函数中,您仍在使用原始列表
您可以这样修复它:
@abc = (undef, 1, undef, undef, undef, 5)
sub zeros {
my @list = @_;
@list = map { $_ // 0 } @list;
return @list;
}
@abc = zeros(@abc);
checking(@abc);
诀窍是返回修改后的列表并将其重新分配给原始变量
如果您使用了严格
和警告
,它会告诉您:
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);
对于5.10%之前的价格
$_ = 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;
}
如果您希望延迟或按需使用零替换undef元素,可以如下所示:
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
你能用
@abc=(0)x2**16
初始化你的列表吗?它将列表设置为2**16个零?你应该始终使用使用strict;使用警告代码>。这会让你的生活更轻松。小心:当你把它作为一个论据传递时,不会复制该列表。原始元素有别名。@sidyll:如果是这样,为什么OP的原始子zero
不起作用?它应该会改变别名,不是吗?事实上@sidyll是对的。解释它是如何工作的。只有将@
赋值给某个对象时,它才会复制值。@辛巴基我正在写一个更详细的答案。@辛巴基我停止了写:-)有一件事我不知道,与数组的初始化方式有关。这是阿德里安·普龙克的回答。如果将别名修改为现有元素,即使将其设置为undef,它也会工作,在OP情况下,它不会工作,因为元素不“存在”。