2014-04-28 29 views
4

給定一個包含其他arrayrefs的arrayref,是否可以使用來自List::MoreUtils的zip函數將嵌套的arrayrefs壓縮在一起?將ArrayRef解包爲X個獨立參數

例如給出這個數組引用:

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) 

我相信有一種方法能夠完美地做到這一點,我只是沒有看到它。任何幫助,將不勝感激。

回答

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]; 
    } 
} 
+0

我最初的想法是,如果我用拉鍊操作上所有的行會產生的轉;我忘了它不會生成嵌套數組。不過,交換指數更清晰。謝謝,這正是我所期待的。 –

2

只需使用的Array::Transposetranspose功能:

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], 
]