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]

In reply to Re^2: Fastest way to "pick without replacement" by choroba
in thread Fastest way to "pick without replacement" by haukex

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.