Have you tried setting TEST to 1? The implementation of grep is wrong, it overwrites the result in each iteration of the for loop. Also, removing just half of the indices shows most of the code needs to be fixed.
#!/usr/bin/perl
use warnings;
use strict;
use Benchmark qw{ cmpthese };
use List::Util qw{ shuffle };
my @numbers = 0 .. 20;
my @indices = shuffle(grep $_ % 2, 0 .. $#numbers);
my @expect = (0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20);
use constant TEST => 1;
cmpthese(-2, {
splice => sub {
my @output = @numbers;
for my $index (sort { $b <=> $a } @indices){
splice @output, $index, 1;
}
join("\0", @output) eq join("\0", @expect) or die "@output\n@e
+xpect" if TEST;
},
grep => sub {
my @output = @numbers[
grep {
my $number = $_;
! grep $number == $_, @indices
} 0 .. $#numbers
];
join("\0", @output) eq join("\0", @expect) or die "@output\n@e
+xpect" if TEST;
},
hash => sub {
my %ha; @ha{0..$#numbers} = ();
for my $index (@indices){
delete $ha{$index};
}
my @output = @numbers[ sort { $a <=> $b } keys %ha ];
join("\0", @output) eq join("\0", @expect) or die "@output\n@e
+xpect" if TEST;
},
hash_slice => sub {
my %indices;
@indices{0 .. $#numbers} = ();
delete @indices{@indices};
my @output = @numbers[sort { $a <=> $b } keys %indices];
join("\0", @output) eq join("\0", @expect) or die "@output\n@e
+xpect" if TEST;
}
});
The order hasn't changed, but the ratios have (result with TEST set back to 0):
Rate grep hash hash_slice splice
grep 65163/s -- -42% -45% -89%
hash 112778/s 73% -- -5% -81%
hash_slice 118725/s 82% 5% -- -80%
splice 580859/s 791% 415% 389% --
(
swl's solution included slightly improved.)
Update:
But using a nested loop (grep in grep) is inefficient and is probably not how I would have changed the original code removing a single element. I'd rather use something like
grep => sub {
my %indices;
@indices{@indices} = ();
my @output = @numbers[
grep ! exists $indices{$_}, 0 .. $#numbers
];
join("\0", @output) eq join("\0", @expect) or die "@output\n@e
+xpect" if TEST;
},
which leads to (TEST = 0)
Rate hash hash_slice grep splice
hash 113323/s -- -6% -41% -80%
hash_slice 120876/s 7% -- -37% -79%
grep 190934/s 68% 58% -- -66%
splice 568237/s 401% 370% 198% --
map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]