in reply to Fastest way to "pick without replacement"
haukex the test you are proposing removes only 1 item from @numbers. If the test removed more than one numbers (or all) one after the other (after a shuffle) could be more realistic (and my hash-based approach could get a chance too :)):
use warnings; use strict; use Benchmark qw/cmpthese/; use List::Util qw/shuffle/; my @numbers = ( 0..20 ); my @indices = shuffle 0..$#numbers; my @expect = ( 0..2,4..20 ); use constant TEST => 0; cmpthese(-2, { splice => sub { my @output = @numbers; for my $index (@indices){ splice @output, 0, 1; } join("\0", @output) eq join("\0", @expect) or die if TEST; }, grep => sub { # https://www.perlmonks.org/?node_id=11123877 my @output; for my $index (@indices){ @output = @numbers[ grep $_ != $index, 0 .. $#numbers ]; } join("\0", @output) eq join("\0", @expect) or die if TEST; }, hash => sub { my %ha; @ha{0..$#numbers} = @numbers; for my $index (@indices){ delete $ha{$index}; } my @output = map { $ha{$_} } sort keys %ha; join("\0", @output) eq join("\0", @expect) or die if TEST; }, }); __END__ Rate grep hash splice grep 30916/s -- -85% -96% hash 205775/s 566% -- -71% splice 707918/s 2190% 244% --
With the above, grep is disadvantaged and splice it just a guess by me (it always removes the first item).
The bottom line: in a loop of removals, hash-based approach can be a contestant too although splice is by far the best but it messes the indices.
bw, bliako
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^2: Fastest way to "pick without replacement"
by choroba (Cardinal) on Nov 21, 2020 at 00:31 UTC | |
|
Re^2: Fastest way to "pick without replacement"
by swl (Prior) on Nov 20, 2020 at 21:54 UTC | |
by swl (Prior) on Nov 21, 2020 at 03:06 UTC | |
by bliako (Abbot) on Nov 20, 2020 at 23:53 UTC |