此问题会继续the previous one关于过滤(变量名称已从array
& search
更改为source
& keys
)。
假设有更多的元素和更多的键。该程序应仅打印以@source
中的任何一个开头的@keys
元素。因此,jjjjk
将被打印,但jjjkk
将不会。
这是解决问题最直接的方法,但使用起来太慢了:
my @source = "aaaaa" .. "kkkkk";
my @keys = "aaaa" .. "jjjj";
.put for @source .grep: /^ @source /;
# produced 4 elements in 60 seconds
# out of 10 ** 4 * 11 = 110_000
# will take ~19 days to finish
使用.Any
和.starts-with()
可以大约快100倍:
my @source = "aaaaa" .. "kkkkk";
my @keys = "aaaa" .. "jjjj";
my $keys_any = @keys.any;
.put for @source .grep: *.starts-with($keys_any);
# produced 700 elements in 110 seconds
# will take ~4.5 hours
如果我们pre-compile正则表达式,它可以更快地工作(~15000x):
my @source = "aaaaa" .. "kkkkk";
my @keys = "aaaa" .. "jjjj";
my $keys = "/@keys.join('|')/".EVAL;
.put for @source .grep: /^ <$keys> /;
# produced all the elements in 100 seconds
然而,它仍然太长,所以我决定利用所有键长度相同的事实。因此,我使用Set
@keys
来检查@source
数组的相同长度的子字符串:
my @source = "aaaaa" .. "kkkkk";
my @keys = "aaaa" .. "jjjj";
my $keys = @keys.Set;
for @source -> $str {
my $substring = $str.substr(0, 4);
if $substring (elem) $keys {
put $str;
next;
}
}
# produced all the elements in 3 seconds
我觉得,我正在重新发明轮子,并且应该有内置的仪器和方法来做这些事情?
答案 0 :(得分:3)
我觉得,我重新发明轮子并且应该有内置的仪器和方法来做这些事情?
有 内置方法来执行此类操作,正如您自己演示的那样。他们应该&#34;只是&#34;优化到足以满足您使用案例的程度。
如果您不喜欢编译器优化,那么您可以为Perl 6 Core Development Fund做出贡献,以便让聪明且敬业的人能够使用它。
答案 1 :(得分:1)
目前,我会坚持使用以下解决方案,该解决方案在正则表达式中使用Sets
的魔力,因为它比我.substr
中的my @source = "aaaaa" .. "kkkkk";
my @keys = "aaaa" .. "jjjj";
my $keys = @keys.Set;
for @source -> $str {
$str ~~ m/ ^ ( . ** 4 ) <?{ ~$0 (elem) $keys }> /;
put $str if so $/;
}
# produced all the elements in 11 seconds
更通用Q值。
ctx.translate(0, canvas.height);
ctx.scale(1, -1);