【问题标题】:Recursivly flatten a multidimensional array递归展平多维数组
【发布时间】:2018-10-13 08:55:21
【问题描述】:

扁平化多维数组的最短方法是什么?
以下是我的意思的一些示例:

# 2D array
my @a = [1,2],[3,4];
say @a».Slip.flat;                # prints (1 2 3 4)
# 3D array
my @b = [[1,2],[3,4]],[[5,6],[7,8]];
say @b».Slip».flat».Slip.flat;    # prints (1 2 3 4 5 6 7 8)
                                  # but needs to know how many dimensions
                                  # there are to flatten

是否可以递归地展平一个数组,例如@b,而无需编写递归下降到其中的 sub 或不知道其维数的任何知识?
我问这个是因为我相信编译器(现在或将来的实现)能够优化更多基于运算符的解决方案而不是 sub。

【问题讨论】:

标签: arrays multidimensional-array raku


【解决方案1】:

不确定是否有更紧凑的方式,但是

say do gather @b.deepmap(*.take);

应该这样做。

如果您不关心展平结果的顺序,

say do gather @b>>.take;

也可能是一种选择,尽管我觉得(ab)使用超级运算符来产生副作用是错误的......


在正确处理 raiph 建议的 HyperWhatever 切片到达核心之前,您可以添加自己的糖 @b[**],通过

覆盖此特定用例
multi sub postcircumfix:<[ ]>(\SELF, HyperWhatever:D $, *% where !*) {
    gather SELF.deepmap(*.take);
}

【讨论】:

  • sub postfix:&lt;[**]&gt; ($_) { gather .deepmap: *.take } 有意义吗?当** 被实施(根据我对费尔南多问题的评论)然后,假设它更快,可以删除这个子。
  • 也许 - 取决于您对“锯齿状”阵列的看法(与成形阵列相反);我猜.[**] 将整个事情弄平可能是有道理的;实现这一点的正确方法是github.com/rakudo/rakudo/blob/master/src/core/…
  • 考虑到这一点,考虑到我们正在谈论 perl(DWIM!)并且 .[2][3].[2;3] 都可以在锯齿状数组上互换工作,将“可能”更改为“是的'
  • :) .oO (Coming to 6.f:@calendar{ July; **[0..2; *-3..*-1] } # Last three business hours of first three days in July.)
【解决方案2】:
say @a>>.List.flat

应该可以解决问题,但是我注意到 Range 会破坏递归:

my @a = [[1,2],[3,4],5,[6,7],[8,9,0],[[1,[2,3,4,[ 23,56,^7]],5,6,]],7,8,9,0];
say @a>>.List.flat;   #prints (1 2 3 4 5 6 7 8 9 0 1 2 3 4 [23 56 ^7] 5 6 7 8 9 0)

我不知道这是否是一个错误。

【讨论】:

  • 不是范围,而是深度——例如say [[[[1,],],],]&gt;&gt;.List.flat
  • 确实你是对的。你能解释一下这个嵌套级别限制是从哪里来的吗?这对我来说并不明显。
  • 我没有看代码来验证,但似乎发生的是&gt;&gt;.List 将仅列出数组的第一个子级别(即它不会递归下降)出于我不太清楚的原因(我本来希望顶层仍然是一个数组);前两个层次对.flat 的调用是透明的,然后会展平另一个层次的深度;但是,如果最后一层是数组,它就会停止,因为它的元素保存在标量容器中,即项目
猜你喜欢
  • 2020-12-23
  • 2018-02-28
  • 2015-12-06
  • 2015-07-14
  • 2012-08-27
  • 2017-12-28
  • 2017-11-28
  • 2020-06-06
  • 1970-01-01
相关资源
最近更新 更多