Here's a benchmark to backup the claim. Replacing the regex
in the map with index gives even a slightly better result,
but that effect is only minimal compared to eliminating the
sort block (linear vs n log n).
#!/usr/bin/perl
use strict;
use warnings;
use Benchmark qw /timethese cmpthese/;
my $elements = 1_000;
my $colon = 50;
our @array = map {$_ = crypt $_, sprintf "%02x" => rand 256;
substr $_, int rand length, 1, ":" if $colon < rand
+100;
$_} 1 .. $elements;
our (@green, @dan, @abi1, @abi2);
cmpthese -10 => {
greenFox => '@green = sort {(($a =~ /:/) <=> ($b =~ /:/)) || $a cm
+p $b}
@array',
'3dan' => '@dan = sort {((index ($a, ":") >= 0) <=>
(index ($b, ":") >= 0)) || $a cmp $b}
+ @array',
abigail1 => '@abi1 = map {substr $_ => 1}
sort
map {/:/ ? "1$_" : "0$_"} @array',
abigail2 => '@abi2 = map {substr $_ => 1}
sort
map {index ($_, ":") >= 0 ? "1$_" : "0$_"}
+@array',
};
warn '@green != @dan', "\n" if "@green" ne "@dan";
warn '@green != @abi1', "\n" if "@green" ne "@abi1";
warn '@green != @abi2', "\n" if "@green" ne "@abi2";
warn '@dan != @abi1', "\n" if "@dan" ne "@abi1";
warn '@dan != @abi2', "\n" if "@dan" ne "@abi2";
warn '@abi1 != @abi2', "\n" if "@abi1" ne "@abi2";
__END__
Rate greenFox 3dan abigail1 abigail2
greenFox 109/s -- -16% -54% -56%
3dan 130/s 19% -- -45% -47%
abigail1 236/s 117% 82% -- -4%
abigail2 246/s 126% 89% 4% --
Abigail |