如何使用 >> 处理嵌套数组并返回一个平面数组?

Kon*_*ele 7 arrays raku

我想知道在 Raku 中有一种简洁的方法来处理嵌套数组(数组数组)并将结果展平吗?当转换平面数组>>.很方便时,但如果我想返回数组并且结果应该是平面的,那么 Raku 中可以使用什么构造?

grammar g {
    rule port       { <pnamelist> + %% ","}
    token pnamelist { <id> +  }
    token id        { \w }
}

class a {
    method port ($/)      { make  $<pnamelist>>>.made  }
    method pnamelist ($/) { make  $<id>>>.made  }
    method id ($/ )       { make $/.Str }
}

my $r = g.parse("ab,cd", :rule('port'), :actions(a) ).made; 

say $r; # [[a b] [c d]]
Run Code Online (Sandbox Code Playgroud)

上面的代码片段输出[[a b] [c d]],但是我真正想要的是[a b c d]. 是否有一种简洁的重写方法,make $<pnamelist>>>.made以便它遍历数组$<pnamelist>并将每个元素收集.made在一个平面列表中,然后为“make”输入什么?

Eli*_*sen 6

make $<pnamelist>.map(*.made.Slip)
Run Code Online (Sandbox Code Playgroud)

当您在slipa 中列出值时map,它们会变平。

>>.在很多情况下使用都很好,但我个人更喜欢.map它,因为它可以提供更大的灵活性。


rai*_*iph 6

TL;DR Flatten 使用位置下标。对于您的示例,将[*;*]或附加[**]$<pnamelist>>>.made。您将获得与 Liz 的解决方案相同的结果。

为什么要使用这个解决方案?

Liz 是对的,map亲戚(fordeepmapduckmapnodemaptree)更灵活,至少在整体上是这样,并且将它们与它们结合起来.Slip就可以了。

但我经常发现使用这些工具和其他工具(包括 hypers)在认知上更简单,创建任何数据结构,而不必担心.Sliping,然后只需添加[*;*...][**]如下所述在最后将结果展平。

最后但并非最不重要的是,它简单而简洁:

method port ($/) { make $<pnamelist>>>.made[**] }
                                           ^^^^
Run Code Online (Sandbox Code Playgroud)

压平 N 级深 [*;*...]

扁平化 N 级深度的一般方法今天如@Larry 一直希望的那样工作

第一个Whatever剥离外部阵列;每个额外的Whatever,由 分隔;,剥离另一个内部嵌套级别。对于您当前的示例,两个Whatevers 可以完成这项工作:

method port ($/) { make $<pnamelist>>>.made[*;*] }
                                           ^^^^^
Run Code Online (Sandbox Code Playgroud)

这产生与 Liz 的解决方案相同的结果:

(a b c d)
Run Code Online (Sandbox Code Playgroud)

如果您希望最终结果具有外部数组,只需将其添加到您认为合适的最终结果中,例如:

method port ($/) { make [ $<pnamelist>>>.made[**] ] }
Run Code Online (Sandbox Code Playgroud)

推土机 [**]

如果你想推倒一个嵌套的数组/列表,剥离所有嵌套,无论多深,你可以编写*;比你可能需要的更多的s。任何额外的东西都不会有任何区别。

但是推土机的愿望是很自然的,并且经常出现,所以有一个操作来完成它而不需要像“只写很多*;”这样的hacky概念是有意义的。

因此,@Larry 在大约十年前指定这样的推土操作也就不足为奇了。它与 Raku 的其他感觉非常一致,使用HyperWhatever( **) 作为索引值。

但是尝试一下:

method port ($/) { make $<pnamelist>>>.made[**] }
                                           ^^^^
Run Code Online (Sandbox Code Playgroud)

目前产量:

HyperWhatever in array index not yet implemented. Sorry.
Run Code Online (Sandbox Code Playgroud)

幸运的是,人们可以很容易地“伪造”它:

sub postfix:< [**] > (\lhs) { gather lhs.deepmap: *.take }
Run Code Online (Sandbox Code Playgroud)

后缀的主体来自here

有了这个,然后更改[*;*]to[**]将适用于您的示例,但无论其左侧嵌套多深,它将继续工作。

假设HyperWhatever数组索引有朝一日作为内置实现,人们将能够删除后缀定义,并且使用它的任何代码都可以在没有它的情况下工作 - 并且可能会获得加速。