in reply to Re: Fastest way to "pick without replacement"
in thread Fastest way to "pick without replacement"
The order hasn't changed, but the ratios have (result with TEST set back to 0):#!/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; } });
(swl's solution included slightly improved.)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% --
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% --
|
|---|