【问题标题】:How to handle nested array with >> and return a flat array?如何使用>>处理嵌套数组并返回一个平面数组?
【发布时间】:2020-11-16 18:03:47
【问题描述】:

我想知道 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]]

上面的 sn-p 输出[[a b] [c d]],但我真正想要的是[a b c d]。有没有一种简洁的方法来重写make $&lt;pnamelist&gt;&gt;&gt;.made,以便它遍历数组$&lt;pnamelist&gt; 并将每个元素.made 收集到一个平面列表中,然后输入“make”?

【问题讨论】:

    标签: arrays raku


    【解决方案1】:

    TL;DR 使用位置下标进行展平。对于您的示例,将[*;*][**] 附加到$&lt;pnamelist&gt;&gt;&gt;.made。您将得到与 Liz 的解决方案相同的结果。

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

    Liz 是对的,map 和亲戚(fordeepmapduckmapnodemapnodemaptree)更灵活,至少在整体上更灵活,并且将它们与 .Slip 结合可以只是门票。

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

    最后但同样重要的是,它简单明了:

    method port ($/) { make $<pnamelist>>>.made[**] }
                                               ^^^^
    

    使用[*;*...] 将 N 层深度展平

    flattening N levels deep works today as @Larry always intended 的一般方法。

    第一个Whatever 去掉了外部数组;每增加一个Whatever,以; 分隔,都会剥离另一个内部嵌套层。对于您当前的示例,两个 Whatevers 完成了这项工作:

    method port ($/) { make $<pnamelist>>>.made[*;*] }
                                               ^^^^^
    

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

    (a b c d)
    

    如果您希望最终结果有一个外部数组,只需将其添加到您认为合适的任何位置即可,例如:

    method port ($/) { make [ $<pnamelist>>>.made[**] ] }
    

    [**]推土机

    如果你想推倒一个嵌套的数组/列表,剥去所有嵌套不管多深,你可以写比你可能写的更多的*;s需要。任何额外的东西都不会产生任何影响。

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

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

    但是尝试一下:

    method port ($/) { make $<pnamelist>>>.made[**] }
                                               ^^^^
    

    目前产量:

    HyperWhatever in array index not yet implemented. Sorry.
    

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

    sub postfix:< [**] > (\lhs) { gather lhs.deepmap: *.take }
    

    后缀的正文来自here

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

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

    【讨论】:

      【解决方案2】:
      make $<pnamelist>.map(*.made.Slip)
      

      当您slip map 中的值列表时,它们会变平。

      在许多情况下使用&gt;&gt;. 很好,但我个人更喜欢.map,因为它允许更大的灵活性。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-05-19
        • 2015-10-21
        • 1970-01-01
        • 2021-06-22
        • 2017-08-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多