我想知道在 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”输入什么?
make $<pnamelist>.map(*.made.Slip)
Run Code Online (Sandbox Code Playgroud)
当您在slip
a 中列出值时map
,它们会变平。
>>.
在很多情况下使用都很好,但我个人更喜欢.map
它,因为它可以提供更大的灵活性。
TL;DR Flatten 使用位置下标。对于您的示例,将[*;*]
或附加[**]
到$<pnamelist>>>.made
。您将获得与 Liz 的解决方案相同的结果。
Liz 是对的,map
亲戚(for
、deepmap
、duckmap
、nodemap
和tree
)更灵活,至少在整体上是这样,并且将它们与它们结合起来.Slip
就可以了。
但我经常发现使用这些工具和其他工具(包括 hypers)在认知上更简单,创建任何数据结构,而不必担心.Slip
ing,然后只需添加[*;*...]
或[**]
如下所述在最后将结果展平。
最后但并非最不重要的是,它简单而简洁:
method port ($/) { make $<pnamelist>>>.made[**] }
^^^^
Run Code Online (Sandbox Code Playgroud)
[*;*...]
扁平化 N 级深度的一般方法今天如@Larry 一直希望的那样工作。
第一个Whatever
剥离外部阵列;每个额外的Whatever
,由 分隔;
,剥离另一个内部嵌套级别。对于您当前的示例,两个Whatever
s 可以完成这项工作:
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
数组索引有朝一日作为内置实现,人们将能够删除后缀定义,并且使用它的任何代码都可以在没有它的情况下工作 - 并且可能会获得加速。
归档时间: |
|
查看次数: |
130 次 |
最近记录: |