递归展开多维数组

9

如何快速将多维数组打平?
以下是一些示例:

# 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)进行递归展平吗?
我之所以问这个问题是因为我相信编译器现在或将来的实现能够更好地优化基于运算符的解决方案而不是子程序。


2
有一天你将能够使用 [**]。但现在,你可以使用 [*;*;*;*;*](你可以指定比实际存在的维度更多)。请参见 https://dev59.com/W1oU5IYBdhLWcg3wu4ni#37230217。你认为你的问题是链接问题的重复还是需要自己回答? - raiph
@raiph,这是有记录的,但它没有被索引:https://docs.perl6.org/language/subscripts#Multiple_dimensions - jjmerelo
2个回答

8

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

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

应该这样做。

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

say do gather @b>>.take;

可能也可以使用超级运算符,但在我的感觉中,滥用超级运算符来处理副作用是不正确的...


在核心支持 raiph 建议的超级切片处理之前,您可以通过添加自己的语法糖 @b[**] 来覆盖此特定用例。

multi sub postcircumfix:<[ ]>(\SELF, HyperWhatever:D $, *% where !*) {
    gather SELF.deepmap(*.take);
}

1
sub postfix:<[**]> ($_) { gather .deepmap: *.take } 有意义吗?当 ** 得到实现(根据我在 Fernando 的问题中的评论)时,假设它更快,那么可以只需删除此子例程。 - raiph
也许 - 这取决于您对“不规则”数组(与形状数组相比)的看法;我猜 .[**] 将整个数组展平可能是有意义的;正确实现这一点的方法应该像 https://github.com/rakudo/rakudo/blob/master/src/core/array_slice.pm6#L448 那样。 - Christoph
1
经过一番思考,考虑到我们正在谈论 Perl(DWIM!),并且在不规则数组上 .[2][3].[2;3] 都可以互换使用,将那个“可能”改为“是”。 - Christoph
2
:) .oO ( 来到 6.f: @calendar{ 七月; **[0..2; *-3..*-1] } # 七月前三天最后三个工作小时. ) - raiph

0
say @a>>.List.flat

这个应该可以解决问题,但是我注意到一个范围会打破递归:

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)

我不知道这是不是一个 bug。


1
不是范围的问题,而是深度的水平 - 例如,请参见 say [[[[1,],],],]>>.List.flat - Christoph
确实,你是对的。你能解释一下这个嵌套级别限制是从哪里来的吗?我觉得这不是很明显。 - HelpfulGuy
我没有查看代码进行验证,但似乎发生的情况是 >>.List 仅会将数组的第一子层列表化(即它不会递归下降),这是由于您传递给超级操作符的操作以及顶层的某种原因(我不太清楚,我本来期望顶层保持为一个数组);这前两个级别对 .flat 的调用是透明的,然后 .flat 将再展开另一层深度;但是,如果最后一层是一个数组,那么它的元素将被保存在标量容器中,这些容器是项目。 - Christoph

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接