如何在Perl 6中切割成形数组?

时间:2018-05-16 01:51:54

标签: multidimensional-array slice perl6

我可以制作一个形状(固定大小)的数组:

my @array[3;3] = (
    < 1 2 3 >,
    < 4 5 6 >,
    < 7 8 9 >
    );

say @array;       # [[1 2 3] [4 5 6] [7 8 9]]
say @array[1;1];  # 5

如何对此进行切片以获得我想要的任何特定列或对角线(行很容易)?

如何将每个维度中的索引列表转换为正确的方括号?

而且,肯定有一些奇特的语法可以阻止我做一些复杂的事情:

my @diagonal = gather {
    my @ends = @array.shape.map: { (0 ..^ $^a).List };
    for [Z] @ends {
        take @array[ $_ ] # how do I make that $_[0];$_[1];...
        };
    }

2 个答案:

答案 0 :(得分:5)

  

如何将其切片以获得我想要的任何特定列或对角线?

据我所知,你现在不能使用带有形状数组的切片语法(尽管你的“(行很容易)”注释会让我感到困惑,每my comment on your post}。

显而易见的解决方案是删除形状并使用切片语法:

my @array = ( < 1 2 3 >, < 4 5 6 >, < 7 8 9 > );

say @array[1];         # 4 5 6 (second row)
say @array[1;*];       # same
say @array[*;1];       # 2 5 8 (second column)

如果你想保留使用异形阵列的边界检查安全性(和/或形状原生阵列的C阵列兼容性,如果我是对的那样)那么你可能需要保留两份副本周围的数组,使用一个来保留形状数组的所需方面,另一个用于切片。

  

如何将每个维度中的索引列表转换为正确的方括号?

最后一个叶子之前的每个维度切片必须与;分开。

我还不清楚这是因为;是一个语句分隔符(在下标中)还是列表列表指示符,也不知道如何以编程方式将索引列表转换为该表单。 (调查仍在继续。)

  

而且,肯定有一些奇特的语法可以阻止我做一些复杂的事情[对角切片]:

say @array[*;{$++}];   # 1 5 9 (diagonal)

;数组下标中的第一个[...]分隔字段对应于数组中的第一个维度,即数组中的行。

指定*表示您想要包含所有行而不是指定特定行。

最后一个字段对应于下标的叶子,即要访问的实际元素。

我首先尝试的只是$++而不是{$++},但这给了我所有元素的第0列,大概是因为语言/ roast和/或Rakudo每次调用时只评估标量索引值一次{1}}下标运算符。

然后我推断如果索引是Callable,它将被调用,并且每行可能会调用一次。这很有用。

我认为这与this code in Rakudo对应。

乍一看,这似乎意味着您无法使用[...]来计算叶片,我注意到roast'd slicing for "calculated indices"不包括使用Callable。也许我只是没有正确看待它。

答案 1 :(得分:1)

您可能已经看到它返回尚未实现的错误(已插入to solve this bug;

Partially dimensioned views of shaped arrays not yet implemented. Sorry.

在这种情况下,最好不要对数组进行取形并使用更传统的方法:

use v6;

my @array = (
    < 1 2 3 >,
    < 4 5 6 >,
    < 7 8 9 >
    );

my @diagonal = gather {
    my @ends = ((0,0),(1,1),(2,2));
    for @ends -> @indices {
        take @array[ @indices[0] ][@indices[1]];
    };
}
say @diagonal;

通过查看the synopsis on the subject,我会说这种方法并没有真正指定。所以说完所有的话,你可能不得不使用EVAL或宏(当它们最终被实现时,当然......)