给定一个包含其他arrayrefs的arrayref,是否可以使用List::MoreUtils
中的zip函数将嵌套的arrayrefs压缩在一起?
例如,给出这个arrayref:
my $matrix = [
[qw( 1 2 3 4)],
[qw( 5 6 7 8)],
[qw( 9 10 11 12)],
[qw(13 14 15 16)],
[qw(17 18 19 20)],
];
我想将每一行压缩在一起,这样我就可以进行转置。预期产出:
[
[qw(1 5 9 13 17)],
[qw(2 6 10 14 18)],
[qw(3 7 11 15 19)],
[qw(4 8 12 16 20)],
];
我最初的尝试是:
# I had hoped the function would unpack the arguments
zip @$matrix;
# ERROR: Not enough arguments for List::MoreUtils::mesh at spiral.pl line 17
# I thought this slice would suffice to unpack them
zip @$matrix[1..scalar @$matrix-1];
# ERROR: Type of arg 1 to List::MoreUtils::mesh must be array (not array slice)
我确信有一种方法可以优雅地做到这一点,我只是没有看到它。任何帮助,将不胜感激。
答案 0 :(得分:6)
zip
函数非常烦人,因为它使用a (\@\@;\@\@\@...)
prototype或类似疯狂的东西。你必须做一个&符号来覆盖原型:&zip(@$matrix)
。
但是,你试图转置矩阵,而不是zip
它(它会产生一个连续的列表,如
[1, 5, 9, 13, 17, 2, 6, 10, 14, 18, 3, 7, 11, 15, 19, 4, 8, 12, 16, 20]
我们可以将natatime
迭代器与zip
结合使用:
my $iter = natatime @$matrix, &zip(@$matrix);
my @transposed;
while (my @column = $iter->()) {
push @transposed, \@column;
}
哪个有效,但这严重阻碍了这个问题。我们只是交换指数:
my $transposed = [];
for my $i (0 .. $#$matrix) {
for my $j (0 .. $#{ $matrix->[0] }) {
$transposed->[$j][$i] = $matrix->[$i][$j];
}
}
答案 1 :(得分:2)
只需使用Array::Transpose
的transpose
功能:
use strict;
use warnings;
use Array::Transpose qw(transpose);
my $matrix = [
[qw( 1 2 3 4)],
[qw( 5 6 7 8)],
[qw( 9 10 11 12)],
[qw(13 14 15 16)],
[qw(17 18 19 20)],
];
my @array=transpose($matrix);
use Data::Dump;
dd \@array;
输出:
[
[1, 5, 9, 13, 17],
[2, 6, 10, 14, 18],
[3, 7, 11, 15, 19],
[4, 8, 12, 16, 20],
]