如何删除引用数组的元素?

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盒子上.升级不是一种选择.

谢谢

DVK*_*DVK 6

为什么不从一开始就贪图?

@array = grep { !/hi/ } @array;
# Or, for *referenced* array
@$arrayRef = grep { !/hi/ } @$arrayRef;
Run Code Online (Sandbox Code Playgroud)

一小组注释,用于澄清评论中出现的问题:

  1. 此方法(或使用grep包括原始海报代码的任何方法)通过新结果数组的大小增加脚本的内存使用量.

    例如,如果脚本(SANS第一阵列)讨论了10MB的内存,原数组了内存15MB,所得阵列注意到内存14MB,那么你的程序的总内存占用量将增加从25MB到39MB,而grep运行.

  2. 一旦grepcomlpetes,原始数组使用的内存将可用于垃圾收集(有一些警告与此帖无关).

  3. 但是 - 这很重要 - 即使最初的15MB数据被垃圾收集,Perl也不会将15MB返回到操作系统 - 例如,脚本的内存占用量将保持为39MB,即使在收集垃圾后也不会降至24MB.

  4. 好的一面是,在程序的整个生命周期内可以释放15MB的内存分配(不考虑内存碎片问题) - 因此,如果你的脚本需要分配额外的1MB,5MB或15MB内存,它的内存占用量不会超过39MB的高点.如果需要17MB的额外内存,最终的内存占用量仅为41MB,而不是56MB.

  5. 如果这个内存算术对你不满意(例如,如果你的原始数组是500MB并且你不愿意容忍程序内存占用量增加到1GB),那么Dallaylaen的答案是一个很好的算法,可以在没有额外内存分配的情况下完成任务


amp*_*ine 0

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)