移动满足某些规则的值

msh*_*210 0 arrays perl

我有一个数字数组,并希望删除数组开头的所有非正数(即零或负数).这就是我所拥有的:

shiftlbl:
$shift = shift @ary;
if (0 >= $shift) {goto shiftlbl;}
else {unshift @ary, $shift;}
Run Code Online (Sandbox Code Playgroud)

有没有一种方法更好(更快),或者工作方式大致相同,但更多Perlish或更容易阅读?

cho*_*oba 6

不使用任何模块,您可以使用

shift @ary while @ary && $ary[0] <= 0;
Run Code Online (Sandbox Code Playgroud)

它不仅更具可读性; 它也快得多.

或者,您可以尝试仅更改一次数组,如果要删除的部分很长,可以加快进程:

use List::Util qw{ first };
my $i = first { $ary[$_] > 0 } 0 .. $#ary;
splice @ary, 0, $i;
Run Code Online (Sandbox Code Playgroud)

因为-1000 .. 200,我得到了

         Rate    old    new splice
old    2782/s     --   -62%   -69%
new    7371/s   165%     --   -17%
splice 8886/s   219%    21%     --
Run Code Online (Sandbox Code Playgroud)

这是整个代码:

#!/usr/bin/perl
use warnings;
use strict;

use List::Util qw{ first };
use Test::More;
use Benchmark qw{ cmpthese };


sub old {
    my @ary = @_;
  shiftlbl:
    my $shift = shift @ary;
    if (0 >= $shift) {goto shiftlbl;}
    else {unshift @ary, $shift;}
    return @ary
}


sub new {
    my @ary = @_;
    shift @ary while @ary && $ary[0] <= 0;
    return @ary
}


sub sp {
    my @ary = @_;
    my $i = first { $ary[$_] > 0 } 0 .. $#ary;
    splice @ary, 0, $i;
    return @ary
}

my @ar = (-1000 .. 200);

is_deeply([old(@ar)], [new(@ar)], 'old - new');
is_deeply([old(@ar)], [sp(@ar)], 'old - splice');

cmpthese(-5,
         {
          old    => sub { old(@ar) },
          new    => sub { new(@ar) },
          splice => sub { sp(@ar)  },

          # Also tried with similar results:
          # old    => 'old( -1000 .. 200)',
          # new    => 'new( -1000 .. 200)',
          # splice => 'sp(  -1000 .. 200)',

         });

done_testing();
Run Code Online (Sandbox Code Playgroud)