Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 如何删除引用数组的元素?_Arrays_Perl_Pass By Reference - Fatal编程技术网

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

Arrays 如何删除引用数组的元素?,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

我想用一个子例程从几个大数组中删除元素。我使用引用以避免复制到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/) { 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增加到39MB

  • 一旦
    grep
    comlpete启动,原始数组使用的内存将可用于垃圾收集(有些警告与本文无关)

  • 然而——这一点很重要——即使最初的15MB数据是垃圾收集的,该15MB数据将不会由Perl返回到操作系统——例如,脚本的内存占用量将保持在39MB,即使在垃圾收集之后也不会下降到24MB

  • 好的一面是,在程序的剩余生命周期中,释放的15MB内存将可用于内存分配(不考虑内存碎片问题)——因此,如果脚本需要额外分配1MB、5MB或15MB内存,其内存占用不会超过39MB的高点。如果它需要17MB的额外内存,那么产生的内存占用将仅为41MB,而不是56MB

  • 如果您对该内存算法不满意(例如,如果您的原始阵列为500MB,并且您不愿意容忍程序内存占用上升到1GB),那么下面是一个在不分配额外内存的情况下执行任务的极好算法


  • 如果你仍然使用
    @$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};