Sha*_*awn 5 arrays perl pass-by-reference
我想用一个子程序从几个大数组中删除元素.我使用引用来避免副本进入子.
@a=qw(ok now what is hi the matter);
sub zonk {
$array=shift; # this is a reference of an array
foreach $i (0..$#$array) { # I saw some say to avoid last element to get size
#if (@$array[$i] =~ /hi/) { delete @$array[$i]; }
#if ($array->[$i] =~ /hi/) { delete $array->[$i]; }
#if ($array->[$i] =~ /hi/) { delete @$array->[$i]; }
if ($array->[$i] =~ /hi/) { print "FOUND "; }
print $array->[$i],"\n";
}
@$array = grep{$_} @$array; # removes empty elements
}
zonk(\@a);
print join(':',@a);
Run Code Online (Sandbox Code Playgroud)
如果我按原样运行上面的程序:
ok
now
what
is
FOUND hi
the
matter
ok:now:what:is:hi:the:matter
Run Code Online (Sandbox Code Playgroud)
但是,如果我使用任何注释行代替我:
delete参数不是hi.pl第10行的HASH元素或切片.
我最初尝试拼接,但随后指数正在转移并混淆了迭代.很高兴知道这篇文章中提到的所有方法,但最有效的是我正在寻找:)
附录:这在我的linux机器上是完美的(我的意思是每条注释行)(ubuntu 9.10,perl 5.10),但上面的错误是在工作时使用perl 5.005_03在我的Windows 7盒子上.升级不是一种选择.
谢谢
为什么不从一开始就贪图?
@array = grep { !/hi/ } @array;
# Or, for *referenced* array
@$arrayRef = grep { !/hi/ } @$arrayRef;
Run Code Online (Sandbox Code Playgroud)
一小组注释,用于澄清评论中出现的问题:
此方法(或使用grep包括原始海报代码的任何方法)将通过新结果数组的大小增加脚本的内存使用量.
例如,如果脚本(SANS第一阵列)讨论了10MB的内存,原数组了内存15MB,所得阵列注意到内存14MB,那么你的程序的总内存占用量将增加从25MB到39MB,而grep运行.
一旦grepcomlpetes,原始数组使用的内存将可用于垃圾收集(有一些警告与此帖无关).
但是 - 这很重要 - 即使最初的15MB数据被垃圾收集,Perl也不会将15MB返回到操作系统 - 例如,脚本的内存占用量将保持为39MB,即使在收集垃圾后也不会降至24MB.
好的一面是,在程序的整个生命周期内可以释放15MB的内存分配(不考虑内存碎片问题) - 因此,如果你的脚本需要分配额外的1MB,5MB或15MB内存,它的内存占用量不会超过39MB的高点.如果需要17MB的额外内存,最终的内存占用量仅为41MB,而不是56MB.
如果这个内存算术对你不满意(例如,如果你的原始数组是500MB并且你不愿意容忍程序内存占用量增加到1GB),那么Dallaylaen的答案是一个很好的算法,可以在没有额外内存分配的情况下完成任务
sub zonk {
$array=shift; # this is a reference of an array
foreach $i (0..$#$array) { # I saw some say to avoid last element to get size
print $array->[$i],"\n";
if ($array->[$i] =~ /hi/) {
delete @{$array}[$i];
}
}
@$array = grep{$_} @$array; # removes empty elements
}
zonk(\@a);
print join(':',@a);
Run Code Online (Sandbox Code Playgroud)