2

所以我应该先说我实际上已经解决了这个问题,但是语法很糟糕,所以我想看看是否有一种更好的 Perl-ish 方法。

我有两个长度为 n (@genes@names) 的数组。我想将它们组合成一个成对值的二维数组。

我现在的方法是;

$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);

不到我想要的。

4

3 回答 3

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 );
于 2013-06-20T23:54:02.627 回答
4

你可以写

my @genes = map [ $names[$_], $lengths[$_] ], 0 .. $#names;
于 2013-06-21T01:00:46.550 回答
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];
    }
}
于 2013-06-21T03:35:34.240 回答