Filtering elements of an array with elements of an

2020-04-06 01:35发布

问题:

I want to filter elements of @array which begin with elements of @search:

my @array = "aaaaa" .. "fffff";
my @search = "aaaa" .. "cccc";
.put for @array .grep: /^ @search /;

The problem is it takes 19 seconds. So, I 'precompile' the regex for grep, and the whole program looks like this:

my @array = "aaaaa" .. "fffff";
my @search = "aaaa" .. "cccc";

my $search = "/@search.join('|')/".EVAL;

.put for @array .grep: * ~~ /^ <$search> /;

Now it takes 0.444s.

The question: is there a built-in Perl 6 method to do such things? Something like inserting a junction into a regex...

回答1:

my @array = "aaaaa" .. "fffff";
my @search = "aaaa" .. "cccc";
my $join = @search.join('|');
my $rx = rx{ ^ <{$join}> };

@array.grep( * ~~ $rx ).map( *.put )

You need to create the join string separately of it will evaluate the array join for each match. But the basically gives you what you want without using EVAL.



回答2:

You could try to speed this up by assembling the regexes.

I am not sure how to do this using pure Perl 6 but Regexp::Assemble is a Perl 5 module that can do this for Perl 5 regexes. You can use Perl 5 modules in Perl 6 code by appending a :from<Perl5> (without a preceding space) to a use statement and then accessing its exported symbols (classes, objects, routines, etc.) as if it was a Perl 6 module:

use v6;

use Regexp::Assemble:from<Perl5>;

my @array = "aaaaa" .. "fffff";
my @search = "aaaa" .. "cccc";
my $ra = Regexp::Assemble.new;
$ra.add( @search );
$ra.anchor_string_begin(1);
.put for @array.grep({so($ra.match( $_ ))});


回答3:

For this kind of search, you can easily use index

say (@array X @search).grep( { defined($^a[0].index($^a[1])) } )
    .grep( { $^a[0].index($^a[1]) == 0 } );

This creates a list of Cs, and seeks the second element of the pair within the first; it returns only the list of those that appear in the first position. defined is needed because it will return Nil if it does not find it. It's not faster than your alternative above, but it's in the same ballpark, with 0.03 system time and ~ 0.30 seconds



标签: raku