簡體   English   中英

滿足某些規則的移位值

[英]Shift values that satisfy some rule

我有一個數字數組,希望刪除數組開頭的所有非正數(即零或負數)。 這是我所擁有的:

shiftlbl:
$shift = shift @ary;
if (0 >= $shift) {goto shiftlbl;}
else {unshift @ary, $shift;}

有沒有一種方法可以更好(更快)地工作,或者可以近似地同樣地工作,但是卻更易讀懂?

無需使用任何模塊,您可以使用

shift @ary while @ary && $ary[0] <= 0;

不僅可讀性強; 它也快得多。

或者,您可以嘗試僅更改一次數組,如果要刪除的部分很長,則可以加快處理過程:

use List::Util qw{ first };
my $i = first { $ary[$_] > 0 } 0 .. $#ary;
splice @ary, 0, $i;

對於-1000 .. 200 ,我得到了

         Rate    old    new splice
old    2782/s     --   -62%   -69%
new    7371/s   165%     --   -17%
splice 8886/s   219%    21%     --

這是完整的代碼:

#!/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();

您可以使用after_incl列表:: MoreUtils

use strict;
use warnings;

use Data::Dump;
use List::MoreUtils qw(after_incl);

my @numbers = (-2, -17, 2, -1, 5, 0);

my @starts_positive = after_incl { $_ > 0 } @numbers;

dd \@starts_positive;

輸出:

[2, -1, 5, 0]

after_incl獲取一個列表,對其應用一個塊,直到該塊返回true,然后從該點返回原始列表的末尾的值列表。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM