Arrays 如何删除引用数组的元素?
我想用一个子例程从几个大数组中删除元素。我使用引用以避免复制到subArrays 如何删除引用数组的元素?,arrays,perl,pass-by-reference,Arrays,Perl,Pass By Reference,我想用一个子例程从几个大数组中删除元素。我使用引用以避免复制到sub @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/) { dele
@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);
如果我按原样运行上述程序,我会得到:
ok
now
what
is
FOUND hi
the
matter
ok:now:what:is:hi:the:matter
但如果我使用任何注释行,我会得到:
delete参数不是hi.pl第10行的哈希元素或切片
我最初尝试了拼接,但后来索引发生了移动,使迭代变得混乱。
很高兴知道本文中提到的所有方法,但是最有效的方法是我正在寻找的:)
附录:这在我的linux机器(Ubuntu9.10,Perl5.10)上非常有效(我指的是每一行注释),但是上面的错误出现在我使用Perl5.00503的Windows7机器上。
升级不是一种选择
谢谢为什么格雷普不马上开始呢
@array = grep { !/hi/ } @array;
# Or, for *referenced* array
@$arrayRef = grep { !/hi/ } @$arrayRef;
一组小注释,用于澄清评论中出现的问题:
grep
的任何方法,包括原始海报的代码)将增加脚本的内存使用量,增加新生成数组的大小
例如,如果脚本(无第一个数组)占用10MB内存,原始数组占用15MB内存,生成的数组占用14MB内存,则在grep
运行时,程序的总内存占用将从25MB增加到39MBgrep
comlpete启动,原始数组使用的内存将可用于垃圾收集(有些警告与本文无关)如果你仍然使用
@$array=grep{…}@$array
,为什么不坚持使用grep{$\u!~/hi/}
但是,如果您的内存非常有限,您可以尝试从顶部开始:
my $i = @$array;
while ($i-->0) {
splice @$array, $i, 1 if $array->[$i] =~ /hi/;
};
但这在最坏情况下的性能为n^2,因此使用C-with-dollars而不是真正的Perl编写可能更好:
my $array = [qw(ok now what is hi the matter)];
my $to = 0;
# move elements backwards
for (my $from=0; $from < @$array; $from++) {
$array->[$from] =~ /hi/ and next;
$array->[$to++] = $array->[$from];
};
# remove tail
splice @$array, $to;
print join ":", @$array;
my$array=[qw(好了,现在怎么了)];
我的$to=0;
#向后移动元素
对于(my$from=0;my$from<@$array;my$from++){
$array->[$from]=~/hi/和next;
$array->[$to++]=$array->[$from];
};
#脱尾
拼接@$array,$to;
打印联接“:”,@$数组;
我仍然不知道为什么
delete$array->[$I]
不起作用,它可以在我目前手头的Perl5.10和5.8上运行 颠倒循环顺序,您可以使用拼接
:
for(my $i = $#array; $i >= 0; --$i) {
#...
}
循环通过每个键,将每个要删除的项目推到一个数组中,然后使用最终删除-一次成功
foreach my $key(keys %$my_array) {
my $val= $my_array->{$key};
if ($val eq "BAD") {
push (@unwanted,$key);
}
}
delete @{$my_array}{@unwanted};
我大错特错了:在@array=grep{…}@array的情况下,Perl会重用内存。走@DVK!这比这稍微复杂一点,但这是一个足够接近的总结。我将发表一篇关于我自己的答案的评论:关于记忆的细节。然而,您的解决方案是我最喜欢的,因为内存有限-+1!使用Perl 5.005在我的Windows 7设备上不起作用。我在原来的问题上增加了一个附录。这看起来是我的答案。如果没有额外的内存使用。。。下面的评论说是这样的so@Shawn-用希望全面的注释修改了答案:内存问题。@Shawn-这是因为这不是指向链接列表的对象意义上的“迭代器”。我不认为Perl有一个真正的“迭代器”,只是手工构建一个链接表类。@肖恩-基本上,Perl数组的行为与链表非常接近,除了列表中的随机插入/删除的异常之外,没有O(1)(但是移位/ unSt/Pop/Press是O(1))。对于我的$i(反向0..$#数组){@ishnid:Yeah,
反向
会更时尚一些,在我看来,同样的效果也不那么尴尬。主要的是整体技术:在应用更改(删除数组元素,对一段文本应用差异,…)时向后走,以避免混淆索引。
foreach my $key(keys %$my_array) {
my $val= $my_array->{$key};
if ($val eq "BAD") {
push (@unwanted,$key);
}
}
delete @{$my_array}{@unwanted};