如何处理带有 >> 和 return 平面数组的嵌套数组?
How to handle nested array with >> and return a flat array?
我想知道 Raku 中是否有一种简洁的方法来处理嵌套数组(数组的数组)和
压平结果?当转换平面数组时 >>.
很方便,但如果我想 return 数组并且结果应该是平面的,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]]
上面的代码片段输出 [[a b] [c d]]
,但我真正想要的是 [a b c d]
。是否有一种简洁的方法来重写 make $<pnamelist>>>.made
以便它遍历数组 $<pnamelist>
并将每个元素 .made
收集在一个平面列表中,然后为 ``make` 输入什么?
make $<pnamelist>.map(*.made.Slip)
当您 slip
map
中的值列表时,它们会变平。
在很多情况下使用 >>.
很好,但我个人更喜欢 .map
,因为它允许更大的灵活性。
TL;DR 使用位置下标展开。对于您的示例,将 [*;*]
或 [**]
附加到 $<pnamelist>>>.made
。您会得到与 Liz 的解决方案相同的结果。
为什么要使用这个解决方案?
Liz 说得对 map
和亲戚 (for
, deepmap
, duckmap
, nodemap
, and tree
) 更灵活,至少在集体上,将它们与 .Slip
结合起来可能只是门票。
但我经常发现使用这些工具和其他工具(包括 hypers)在认知上更简单,可以创建任何数据结构,而无需担心 .Slip
ing,然后在最后将结果展平只需附加 [*;*...]
或 [**]
,如下所述。
最后但同样重要的是,它简单明了:
method port ($/) { make $<pnamelist>>>.made[**] }
^^^^
用 [*;*...]
深度展平 N 个级别
的一般方法。
第一个Whatever
剥离外层数组;每个额外的 Whatever
,由 ;
分隔,剥离另一个内部嵌套层。对于您当前的示例,两个 Whatever
可以完成工作:
method port ($/) { make $<pnamelist>>>.made[*;*] }
^^^^^
这会产生与 Liz 的解决方案相同的结果:
(a b c d)
如果你希望最终结果有一个外部数组,只要在你认为合适的地方添加到最终结果即可,例如:
method port ($/) { make [ $<pnamelist>>>.made[**] ] }
推土机 [**]
如果你想推土机嵌套array/list,剥离所有嵌套,无论有多深,你可以写的 *;
比你可能需要的多。任何额外的东西都不会产生任何影响。
但是推土机的愿望是很自然的,而且经常出现,所以有一个操作可以做到这一点而不需要像“只写很多 *;
”这样的骇人听闻的概念是有意义的。
因此,@Larry 在大约十年前指定了这样一个 bulldozing 操作也就不足为奇了。使用 HyperWhatever
(**
) 作为索引值,这与 Raku 的其他感觉非常一致。
但尝试一下:
method port ($/) { make $<pnamelist>>>.made[**] }
^^^^
当前产量:
HyperWhatever in array index not yet implemented. Sorry.
幸运的是,可以很容易地“伪造”它:
sub postfix:< [**] > (\lhs) { gather lhs.deepmap: *.take }
后缀正文来自。
有了这个,然后将 [*;*]
更改为 [**]
将适用于您的示例,但无论其左侧嵌套的深度如何,都将继续工作。
并且假设数组索引中的 HyperWhatever
有朝一日作为内置实现,人们将能够删除后缀定义,并且使用它的任何代码在没有它的情况下也能正常工作——而且,大概会得到一个加速。
我想知道 Raku 中是否有一种简洁的方法来处理嵌套数组(数组的数组)和
压平结果?当转换平面数组时 >>.
很方便,但如果我想 return 数组并且结果应该是平面的,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]]
上面的代码片段输出 [[a b] [c d]]
,但我真正想要的是 [a b c d]
。是否有一种简洁的方法来重写 make $<pnamelist>>>.made
以便它遍历数组 $<pnamelist>
并将每个元素 .made
收集在一个平面列表中,然后为 ``make` 输入什么?
make $<pnamelist>.map(*.made.Slip)
当您 slip
map
中的值列表时,它们会变平。
在很多情况下使用 >>.
很好,但我个人更喜欢 .map
,因为它允许更大的灵活性。
TL;DR 使用位置下标展开。对于您的示例,将 [*;*]
或 [**]
附加到 $<pnamelist>>>.made
。您会得到与 Liz 的解决方案相同的结果。
为什么要使用这个解决方案?
Liz 说得对 map
和亲戚 (for
, deepmap
, duckmap
, nodemap
, and tree
) 更灵活,至少在集体上,将它们与 .Slip
结合起来可能只是门票。
但我经常发现使用这些工具和其他工具(包括 hypers)在认知上更简单,可以创建任何数据结构,而无需担心 .Slip
ing,然后在最后将结果展平只需附加 [*;*...]
或 [**]
,如下所述。
最后但同样重要的是,它简单明了:
method port ($/) { make $<pnamelist>>>.made[**] }
^^^^
用 [*;*...]
深度展平 N 个级别
第一个Whatever
剥离外层数组;每个额外的 Whatever
,由 ;
分隔,剥离另一个内部嵌套层。对于您当前的示例,两个 Whatever
可以完成工作:
method port ($/) { make $<pnamelist>>>.made[*;*] }
^^^^^
这会产生与 Liz 的解决方案相同的结果:
(a b c d)
如果你希望最终结果有一个外部数组,只要在你认为合适的地方添加到最终结果即可,例如:
method port ($/) { make [ $<pnamelist>>>.made[**] ] }
推土机 [**]
如果你想推土机嵌套array/list,剥离所有嵌套,无论有多深,你可以写的 *;
比你可能需要的多。任何额外的东西都不会产生任何影响。
但是推土机的愿望是很自然的,而且经常出现,所以有一个操作可以做到这一点而不需要像“只写很多 *;
”这样的骇人听闻的概念是有意义的。
因此,@Larry 在大约十年前指定了这样一个 bulldozing 操作也就不足为奇了。使用 HyperWhatever
(**
) 作为索引值,这与 Raku 的其他感觉非常一致。
但尝试一下:
method port ($/) { make $<pnamelist>>>.made[**] }
^^^^
当前产量:
HyperWhatever in array index not yet implemented. Sorry.
幸运的是,可以很容易地“伪造”它:
sub postfix:< [**] > (\lhs) { gather lhs.deepmap: *.take }
后缀正文来自
有了这个,然后将 [*;*]
更改为 [**]
将适用于您的示例,但无论其左侧嵌套的深度如何,都将继续工作。
并且假设数组索引中的 HyperWhatever
有朝一日作为内置实现,人们将能够删除后缀定义,并且使用它的任何代码在没有它的情况下也能正常工作——而且,大概会得到一个加速。