我正在尝试实现一个以数组作为参数的子例程(或使用多个参数 - 仍然没有完全理解差异),并根据该数组是否为递增序列返回真或假(每个数字必须是比上一个多1个):
isIncreasingArray(1,2,3,4); # true
isIncreasingArray(1,2,3,1); # false
isIncreasingArray(0,9,1); # false
isIncreasingArray(-2,-1,0); # true
isIncreasingArray(1,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
将返回一个由单个元素组成的列表,因此为真。一个光秃秃的return
当您想要返回 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
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;
}
=== 案例:unordered_large_mid
速率平坦引用
持平 4.64/s -- -18%
引用 5.67/s 22% --
=== 案例:ordered_small
率引用平
引用 154202/s -- -11%
平 173063/s 12% --
=== 案例:ordered_large
速率平坦引用
持平 2.41/s -- -13%
引用 2.78/s 15% --
=== 案例:unordered_large_beg
速率平坦引用
持平 54.2/s -- -83%
引用 315/s 481% --
=== 案例:unordered_large_end
速率平坦引用
持平 2.41/s -- -12%
引用 2.74/s 14% --
关于perl - 在 Perl 中,如何测试一个序列的形式是否为 n、n + 1、n + 2、...、n + k?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8166123/