在Perl 6

时间:2017-11-16 11:58:08

标签: perl6

此问题会继续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

我觉得,我正在重新发明轮子,并且应该有内置的仪器和方法来做这些事情?

2 个答案:

答案 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);