所以我应该先说这个我已经解决了这个问题,但语法很糟糕,所以我想看看是否有一种Perl-ish方式做得更好。
我有两个长度为n的数组(@genes
和@names
)。我想将它们组合成一个配对值的2D数组。
我现在的做法是;
$Num = Number of elements in each array
my @genes = ();
foreach my $i ( 0 .. $num-1 ) {
foreach my $j ( 0 .. 1 ) {
if ($j == 0){ push @{ $genes[$i] }, $names[$i];}
if ($j == 1){ push @{ $genes[$i] }, $lengths[$i];}
}
}
但是这需要为每个附加列提供一个显式行(现在我有两个 - 名称和长度)。它也很可怕。只有母亲可以爱的代码。
任何想法。注意
@genes = (\@lengths, \@names);
不实现我想要的目标。
答案 0 :(得分:5)
你至少可以这样做:
foreach my $i ( 0 .. $num-1 ) {
push @genes, [$names[$i], $lengths[$i]];
}
如果您不关心输入数组,可以使用它们:
push @genes, [shift @names, shift @lengths] while @names;
还有一些模块可用于迭代多个列表。例如,使用List::MoreUtils::each_array
:
use List::MoreUtils qw( each_array );
my $it = each_array( @names, @lengths );
while (my ($n, $l) = $it->()) {
push @genes, [$n, $l];
}
此外,List::MoreUtils::pairwise
:
use List::MoreUtils qw( pairwise );
@genes = pairwise{ [our $a, our $b] } @names, @lengths;
ysth建议Algorithm::Loops::MapCarE
:
use Algorithm::Loops 'MapCarE';
@genes = MapCarE { \@_ } \( @names, @lengths );
答案 1 :(得分:4)
你可以写
my @genes = map [ $names[$_], $lengths[$_] ], 0 .. $#names;
答案 2 :(得分:1)
顺便提一下,只需删除一些代码就可以清除原始代码 不必要的逻辑:
foreach my $i ( 0 .. $num-1 ) {
foreach my $j ( 0 .. 1 ) {
if ($j == 0){ push @{ $genes[$i] }, $names[$i];}
if ($j == 1){ push @{ $genes[$i] }, $lengths[$i];}
}
}
你循环遍历0和1,然后测试你是否在0或1,然后 执行一个动作或另一个动作?只需每次执行两个操作:
foreach my $i ( 0 .. $num-1 ) {
push @{$genes[$i]}, $names[$i];
push @{$genes[$i]}, $lengths[$i]
}
可能你开始想要遍历索引,然后想到你
由于内部阵列尚未存在,因此无法做到这一点,并且回归到了
这个push
构造。但是,呃,在您push
之前,数组不存在
他们也来到这里。循环索引很好:
my @helper = (\@names, \@lengths);
foreach my $i ( 0 .. $#names ) {
foreach my $j ( 0 .. 1 ) {
$genes[$i][$j] = $helper[$j][$i];
}
}