在Perl中,如何测试序列的形式是否为n,n+;1,n+;2,…,n+;K

在Perl中,如何测试序列的形式是否为n,n+;1,n+;2,…,n+;K,perl,Perl,我正在尝试实现一个子程序,该子程序将一个数组作为其参数(或使用多个参数-仍然没有完全消除差异),并根据该数组是否为递增序列返回true或false(每个数字必须比最后一个数字多1个): 这就是我想到的: sub isIncreasingArray { my $last; foreach $n (@_) { return 0 if defined($last) && $last != $n - 1; $last = int($n)

我正在尝试实现一个子程序,该子程序将一个数组作为其参数(或使用多个参数-仍然没有完全消除差异),并根据该数组是否为递增序列返回true或false(每个数字必须比最后一个数字多1个):

这就是我想到的:

sub isIncreasingArray {

    my $last;

    foreach $n (@_) {
        return 0 if defined($last) && $last != $n - 1;
        $last = int($n);
    }

    return 1;

}

我对Perl非常陌生,我想知道是否有更简单或更简洁的方法来实现这一点?另外,我写的东西是否符合最佳实践?

我最终得到的东西比你的要长一点。这意味着,我想,您的解决方案没有问题:)


这是我能找到的最短形式,检查地图中的每个元素是否等于增加的自我,返回一个0和1的集合,计算1并与集合的原始大小匹配

print isIncreasingArray(1,2,3),"\n";
print isIncreasingArray(1,2,1),"\n";
print isIncreasingArray(1,2),"\n";
print isIncreasingArray(1),"\n";

sub isIncreasingArray {
  $i = $_[0];
  (scalar grep { 1 == $_ } map { $i++ == $_ } @_) == scalar(@_) || 0;
}
有两点:

  • 为了提高效率,尤其是最小化内存占用,您可能希望将对数组的引用传递给子例程

  • 在列表上下文中,
    return 0
    将返回一个由单个元素组成的列表,因此为true。当您希望返回
    false
    并在所有上下文中执行该操作时,一个简单的
    返回就足够了

  • 也许可以通过比较第一个和最后一个、第二个和第二个之间的差异,将比较的数量减少一半。这样,差异就等于指数的差异,但我现在想得不太清楚

    这是一个与你的稍有不同的版本。请注意,您应该使用
    strict
    ,并确保使用
    my
    确定循环变量的范围:

    #!/usr/bin/env perl
    
    use strict; use warnings;
    
    use Carp qw(croak);
    use Test::More;
    
    ok(     isSimplyIncreasingSequence( [ 1298 ]  ) ); # true
    ok(     isSimplyIncreasingSequence( [1,2,3,4] ) ); # true
    ok( not isSimplyIncreasingSequence( [1,2,3,1] ) ); # false
    ok( not isSimplyIncreasingSequence( [0,9,1]   ) ); # false
    ok(     isSimplyIncreasingSequence( [-2,-1,0] ) ); # true
    ok( not isSimplyIncreasingSequence( [1,1,1,1] ) ); # false
    
    done_testing();
    
    sub isSimplyIncreasingSequence {
        my ($seq) = @_;
    
        unless (defined($seq)
                and ('ARRAY' eq ref $seq)) {
            croak 'Expecting a reference to an array as first argument';
        }
    
        return 1 if @$seq < 2;
    
        my $first = $seq->[0];
    
        for my $n (1 .. $#$seq) {
            return unless $seq->[$n] == $first + $n;
        }
    
        return 1;
    }
    
    #/usr/bin/env perl
    严格使用;使用警告;
    使用鲤鱼qw(croak);
    使用测试::更多;
    ok(ISimplyincreasingsequence([1298]);#真的
    ok(ISimplyIncreasingSequence([1,2,3,4]);#真的
    ok(不是简单的增量序列([1,2,3,1]);#假的
    ok(不是简单的增量序列([0,9,1]);#假的
    ok(ISimplyincreasingsequence([-2,-1,0]);#真的
    ok(不是简单的增量序列([1,1,1,1]);#假的
    完成测试();
    子序列{
    我的($seq)=@;
    除非(定义为($seq)
    和('阵列'eq参考$seq)){
    croak'期望数组引用作为第一个参数';
    }
    如果@$seq<2,则返回1;
    my$first=$seq->[0];
    对于我的$n(1..$#$seq){
    除非$seq->[$n]==$first+$n,否则返回;
    }
    返回1;
    }
    
    当然,还有一些基准:

    #!/usr/bin/env perl
    
    use strict; use warnings;
    
    use Benchmark qw( cmpthese );
    use Carp qw( croak );
    
    my %cases = (
        ordered_large => [1 .. 1_000_000],
        ordered_small => [1 .. 10],
        unordered_large_beg => [5, 1 .. 999_000],
        unordered_large_mid => [1 .. 500_000, 5, 500_002 .. 1_000_000],
        unordered_large_end => [1 .. 999_999, 5],
    );
    
    for my $case (keys %cases) {
        print "=== Case: $case\n";
        my $seq = $cases{$case};
        cmpthese -3, {
            'ref'  => sub { isSimplyIncreasingSequence($seq) },
            'flat' => sub {isIncreasingArray(@{ $seq } ) },
        };
    }
    
    sub isSimplyIncreasingSequence {
        my ($seq) = @_;
    
        unless (defined($seq)
                and ('ARRAY' eq ref $seq)) {
            croak 'Expecting a reference to an array as first argument';
        }
    
        return 1 if @$seq < 2;
    
        my $first = $seq->[0];
    
        for my $n (1 .. $#$seq) {
            return unless $seq->[$n] == $first + $n;
        }
    
        return 1;
    }
    
    sub isIncreasingArray {
    
        my $last;
    
        foreach my $n (@_) {
            return 0 if defined($last) && $last != $n - 1;
            $last = int($n);
        }
    
        return 1;
    
    }
    
    #/usr/bin/env perl
    严格使用;使用警告;
    使用基准qw(CMP准则);
    使用鲤鱼qw(croak);
    我的%cases=(
    有序大=>[1..1\u 000\u 000],
    有序_small=>[1..10],
    无序\u大\u beg=>[5,1..999\u 000],
    无序的(大)(中)=>[1..500(000),5500(002)..1(000)],,
    无序\u大\u端=>[1..999\u 999,5],
    );
    对于我的$case(关键字%cases){
    打印“==案例:$Case\n”;
    my$seq=$cases{$case};
    cmpthese-3{
    'ref'=>sub{isSimplyIncreasingSequence($seq)},
    'flat'=>sub{isiincreasingarray(@{$seq}}),
    };
    }
    子序列{
    我的($seq)=@;
    除非(定义为($seq)
    和('阵列'eq参考$seq)){
    croak'期望数组引用作为第一个参数';
    }
    如果@$seq<2,则返回1;
    my$first=$seq->[0];
    对于我的$n(1..$#$seq){
    除非$seq->[$n]==$first+$n,否则返回;
    }
    返回1;
    }
    子增量阵列{
    我的最后一美元;
    付我的$n(@){
    如果定义了($last)&&$last!=$n-1,则返回0;
    $last=int($n);
    }
    返回1;
    }
    
    ==案例:无序\u大\u中 速率平坦参考 平4.64/s--18% 参考5.67/s 22%-- ==大小写:有序\u小 速率参考平面 参考号154202/s--11% 173063/s单位12%-- ==大小写:订购的\u大 速率平坦参考 单位2.41/s--13% 参考2.78/s 15%-- ==案例:无序\u大\u 速率平坦参考 单位54.2/s--83% 参考315/s 481%-- ==案例:无序\u大\u端 速率平坦参考 单位2.41/s--12% 参考2.74/s 14%--使用6“交叉点”之前的交叉点:

    (如果约束是$x[$n+1]-$x[$n]==1,那么减去1也会产生“Perl真值条件”。)

    实际上,考虑到“无”连接操作符有点落后于这个概念,所以我将使用
    all

    sub is_increasing_list { 
        use List::MoreUtils qw<all>;
        my $a = shift;
        return all { [ ( $a, undef ) = ( $_, ( $_ - $a == 1 )) ]->[-1]; } @_;
    }
    
    sub正在增加列表{
    使用列表::MoreUtils qw;
    我的$a=班次;
    返回所有{[($a,unde)=($),($-$a==1))]->[-1];}@;
    }
    
    为什么没有人想出智能匹配解决方案

    虽然这个解决方案不如其他一些解决方案有效,但它还有使用字符串的额外好处

    编辑

    对于空列表和单个元素列表,Sub现在返回true,因为:

    使用严格;
    使用警告;
    使用5.010;
    sub是_简单地_增加{@124;<2 | |@{~[$\[0]..$\[-1]}
    比如说(你只是在增加(1,2,3,4);“真的”:“假的”;#真的
    比如(你只是在增加(1,2,3,1)吗?“真”:“假”);#假的
    比如(你只是在增加(0,9,1)吗?“真”:“假”);#假的
    比方说(你只是在增加(-2,-1,0);“真”:“假”);#真的
    比如(你只是在增加(1,1,1,1)吗?“真”:“假”);#假的
    比如(你只是在增加(1,4,1,-1)吗?“真”:“假”);#假的
    比如说(你只是在增加('a','c')?'true':'false');#假的
    比如(你只是在增加('love'.'perl')?'true':'false');#真的
    比如说(你只是在增加(2)‘真’:‘假’;#真的
    比如说(你只是在增加吗?“真的”:“假的”);#真的
    

    我喜欢我的潜艇只有一条线

    这里必须有人加入函数式编程解决方案,因为这种数学公式只要求递归

    Th
    #!/usr/bin/env perl
    
    use strict; use warnings;
    
    use Benchmark qw( cmpthese );
    use Carp qw( croak );
    
    my %cases = (
        ordered_large => [1 .. 1_000_000],
        ordered_small => [1 .. 10],
        unordered_large_beg => [5, 1 .. 999_000],
        unordered_large_mid => [1 .. 500_000, 5, 500_002 .. 1_000_000],
        unordered_large_end => [1 .. 999_999, 5],
    );
    
    for my $case (keys %cases) {
        print "=== Case: $case\n";
        my $seq = $cases{$case};
        cmpthese -3, {
            'ref'  => sub { isSimplyIncreasingSequence($seq) },
            'flat' => sub {isIncreasingArray(@{ $seq } ) },
        };
    }
    
    sub isSimplyIncreasingSequence {
        my ($seq) = @_;
    
        unless (defined($seq)
                and ('ARRAY' eq ref $seq)) {
            croak 'Expecting a reference to an array as first argument';
        }
    
        return 1 if @$seq < 2;
    
        my $first = $seq->[0];
    
        for my $n (1 .. $#$seq) {
            return unless $seq->[$n] == $first + $n;
        }
    
        return 1;
    }
    
    sub isIncreasingArray {
    
        my $last;
    
        foreach my $n (@_) {
            return 0 if defined($last) && $last != $n - 1;
            $last = int($n);
        }
    
        return 1;
    
    }
    
    === Case: unordered_large_mid Rate flat ref flat 4.64/s -- -18% ref 5.67/s 22% -- === Case: ordered_small Rate ref flat ref 154202/s -- -11% flat 173063/s 12% -- === Case: ordered_large Rate flat ref flat 2.41/s -- -13% ref 2.78/s 15% -- === Case: unordered_large_beg Rate flat ref flat 54.2/s -- -83% ref 315/s 481% -- === Case: unordered_large_end Rate flat ref flat 2.41/s -- -12% ref 2.74/s 14% --
    sub is_increasing_list { 
        use List::MoreUtils qw<none>;
        my $a = shift;
        return none { 
            ( my $v, $a ) = (( $_ - $a != 1 ), $_ ); 
            $v;
        } @_;
    }
    
    return none { [ ( $a, undef ) = ( $_, ( $_ - $a - 1 )) ]->[-1]; } @_;
    
    sub is_increasing_list { 
        use List::MoreUtils qw<all>;
        my $a = shift;
        return all { [ ( $a, undef ) = ( $_, ( $_ - $a == 1 )) ]->[-1]; } @_;
    }
    
    use strict;
    use warnings;
    use 5.010;
    
    sub is_simply_increasing { @_ < 2 || @_ ~~ [$_[0] .. $_[-1]] }
    
    say (  is_simply_increasing(1,2,3,4)        ? 'true' : 'false' );  # true
    say (  is_simply_increasing(1,2,3,1)        ? 'true' : 'false' );  # false
    say (  is_simply_increasing(0,9,1)          ? 'true' : 'false' );  # false
    say (  is_simply_increasing(-2,-1,0)        ? 'true' : 'false' );  # true
    say (  is_simply_increasing(1,1,1,1)        ? 'true' : 'false' );  # false
    say (  is_simply_increasing(1,4,1,-1)       ? 'true' : 'false' );  # false
    say (  is_simply_increasing('a','c')        ? 'true' : 'false' );  # false
    say (  is_simply_increasing('love'..'perl') ? 'true' : 'false' );  # true
    say (  is_simply_increasing(2)              ? 'true' : 'false' );  # true
    say (  is_simply_increasing()               ? 'true' : 'false' );  # true
    
    sub isIncreasingArray {
      return 1 if @_ <= 1;   
      return (pop(@_) - $_[-1] == 1) && isIncreasingArray(@_);
    }
    
    isIncreasingArray(1,2,3,4); 
    
    @a = (1,2,3,4);
    $answer = isIncreasingArray(@a); 
    
    print isIncreasingArray(1..10000), "\n"; # true
    
    sub isSimplyIncreasingSequence {
       return 1 if @_ < 2;
       return 0 if $_[-1] - $_[0] != $#_;
       ...
    }