in reply to Re: grep surprise
in thread grep surprise

In this case, the firstidx function in List::MoreUtils may be a better fit, because it provides a simpler syntax:

my $i1 = firstidx { $_ == 1 } @array;

And it’s faster too:

use strict; use warnings; use feature qw( state ); use Benchmark qw( cmpthese ); use List::Util qw( first shuffle ); use List::MoreUtils qw( firstidx indexes ); my @array = shuffle (1 .. 1e6); cmpthese ( 10, { grep => sub { _grep() }, first => sub { _first() }, indexes => sub { _indexes() }, firstidx => sub { _firstidx() }, } ); sub _grep { state $init = 1; my ($i1) = grep { $array[$_] == 1 } 0 .. $#array; my ($i2) = grep { $array[$_] == 2 } 0 .. $#array; my ($i3) = grep { $array[$_] == 3 } 0 .. $#array; if ($init) { printf "<%d> <%d> <%d>\n", $i1, $i2, $i3; $init = 0; } } sub _first { state $init = 1; my $i1 = first { $array[$_] == 1 } (0 .. $#array); my $i2 = first { $array[$_] == 2 } (0 .. $#array); my $i3 = first { $array[$_] == 3 } (0 .. $#array); if ($init) { printf "<%d> <%d> <%d>\n", $i1, $i2, $i3; $init = 0; } } sub _indexes { state $init = 1; my $i1 = indexes { $array[$_] == 1 } (0 .. $#array); my $i2 = indexes { $array[$_] == 2 } (0 .. $#array); my $i3 = indexes { $array[$_] == 3 } (0 .. $#array); if ($init) { printf "<%d> <%d> <%d>\n", $i1, $i2, $i3; $init = 0; } } sub _firstidx { state $init = 1; my $i1 = firstidx { $_ == 1 } @array; my $i2 = firstidx { $_ == 2 } @array; my $i3 = firstidx { $_ == 3 } @array; if ($init) { printf "<%d> <%d> <%d>\n", $i1, $i2, $i3; $init = 0; } }

Output:

23:20 >perl 1940_SoPW.pl <748548> <843435> <178789> <748548> <843435> <178789> <748548> <843435> <178789> <748548> <843435> <178789> Rate grep indexes first firstidx grep 1.19/s -- -1% -34% -52% indexes 1.20/s 1% -- -34% -51% first 1.81/s 53% 51% -- -27% firstidx 2.47/s 108% 106% 37% -- 23:20 >

Cheers,

Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Replies are listed 'Best First'.
Re^3: grep surprise
by LanX (Saint) on Nov 12, 2018 at 16:04 UTC
    Since you are testing the case where all entries are unique, you may want to add benchmarks for hash lookups.

    Actually two: there is no doubt that a lookup is way faster, the essential question is if the initialization of the hash needs to be included.

    In the later case I'd prefer a hash slice then.

    @lookup{@array} = (0.. $#array);

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery FootballPerl is like chess, only without the dice