在Perl中,如何测试序列是否为n,n 1,n 2,…,n k?

前端之家收集整理的这篇文章主要介绍了在Perl中,如何测试序列是否为n,n 1,n 2,…,n k?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我试图实现一个使用数组作为参数的子例程(或使用多个参数 – 仍然没有完全区分),并且返回true或false,这取决于该数组是否是递增序列(每个数字必须是1以上):
isIncreasingArray(1,2,3,4); # true
isIncreasingArray(1,1); # false
isIncreasingArray(0,9,1);   # false
isIncreasingArray(-2,-1,0); # true
isIncreasingArray(1,1,1); # false

这是我想出来的:

sub isIncreasingArray {

    my $last;

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

    return 1;

}

我对Perl很新,我想知道是否有更简单或更简洁的方法来实现这一点?还有,我是按照最佳做法写的?

解决方法

几点:

>为了提高效率,特别是最小化内存占用,您可能希望将对数组的引用传递给子程序。
>在列表上下文中,return 0将返回由单个元素组成的列表,因此将为true。当您要返回false并且在所有上下文中执行该作业时,返回足够的空值。

通过比较第一个和最后一个,第二个和第二个之间的差异等来看比较差异可能会减少一半,以看到差异在索引上的差异,但我现在并没有想到这一点。

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

#!/usr/bin/env perl

use strict; use warnings;

use Carp qw(croak);
use Test::More;

ok(     isSimplyIncreasingSequence( [ 1298 ]  ) ); # true
ok(     isSimplyIncreasingSequence( [1,4] ) ); # true
ok( not isSimplyIncreasingSequence( [1,1] ) ); # false
ok( not isSimplyIncreasingSequence( [0,1]   ) ); # false
ok(     isSimplyIncreasingSequence( [-2,0] ) ); # true
ok( not isSimplyIncreasingSequence( [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

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%   --

猜你在找的Perl相关文章