20ish lines of verbose code involving hashes, arrays and grouping, in comparison to a magic piece of regex which does in 3 lines the same thing.
use Benchmark q{:all};
my @lsf_indices = ( 1000,1001,1002,1003,1006,3000,3300,3301,3302,3303,3304,3305,3306,3998,3999,4000,4001,4002);
my %methods = (
regex => sub {
my $array_string = join q{,}, @lsf_indices;
$array_string =~ s/\b(\d+)(,((??{$+ + 1}))\b)+/$1-$+/g;
$array_string = q{[} . $array_string . q{]};
},
verbose => sub {
my ( $previous, $current_working_index );
my %consecutive;
foreach my $index ( @lsf_indices ) {
if ( $previous && ( $index == $previous + 1 ) ) {
push @{ $consecutive{ $current_working_index } }, $index;
$previous = $index;
} else {
$previous = $index;
$current_working_index = $index;
push @{ $consecutive{ $current_working_index } }, $index;
}
}
my @array;
foreach my $index ( sort { $a <=> $b } keys %consecutive ) {
if ( scalar @{ $consecutive{$index} } == 1 ) {
push @array, qq{$consecutive{$index}->[0]};
} else {
my $last = pop @{ $consecutive{$index} };
my $first = shift @{ $consecutive{$index} };
push @array, $first . q{-} . $last;
}
}
my $array_string = q{[} . ( join q{,}, @array ) . q{]};
},
);
cmpthese( 30_000, \%methods);
timethese( 30_000, \%methods);
Result
home$ ./benchmark.pl
Rate regex verbose
regex 6048/s -- -72%
verbose 21898/s 262% --
Benchmark: timing 30000 iterations of regex, verbose...
regex: 5 wallclock secs ( 4.96 usr + 0.01 sys = 4.97 CPU) @ 6036.22/s (n=30000)
verbose: 1 wallclock secs ( 1.37 usr + 0.00 sys = 1.37 CPU) @ 21897.81/s (n=30000)
Verbose lines of code is around 5 times faster. Happy :) Code I can read, and speed benefits as well.
Admittedly, a bit of an exercise, since this isn't really a bottleneck. ;)