2

在 Perl 中编写以下代码的最有效方法是什么:

my $index = 0;
foreach ( @spec ) {
    if ( $module =~ m/$_/ ) {
        splice(@spec, $index, 0, $module);
        last;         
    }
    $index++;
}

这工作正常。只是好像有点啰嗦。这个想法是,我$module在数组中找到匹配项的地方添加一个条目。我想将数组保持在一定的顺序并排序。

即如果我的数组是[a,b,c,d]并且我$module是' c',我希望结果数组是[a,b,c,c,d]

4

3 回答 3

5

你想要“更有效的冗长”???我想您不是要打高尔夫球,而是要更具可读性的代码。

@spec = map { $_ eq $module ? ($_, $_) : $_ } @spec;
于 2013-05-10T13:09:06.797 回答
1

http://perldoc.perl.org/perlsyn.html#For-Loops提供了这种智慧:

如果 LIST 的任何部分是一个数组,如果你在循环体中添加或删除元素,foreach 将变得非常混乱,例如使用 splice。所以不要那样做。

如果您必须这样做(在这种情况下不合适),请这样做:

for ( my $index = 0; $index < @array; ++$index ) {
    my $elem = $array[$index];
    if ( ... ) {
        splice( @array, $index, 0, $elem );
        ++$index;
    }
}

或这个:

for ( my $index = $#array; $index >= 0; --$index ) {
    my $elem = $array[$index];
    if ( ... ) {
        splice( @array, $index, 0, $elem );
    }
}
于 2013-05-10T16:46:15.403 回答
1

您的代码看起来与我所做的差不多,只是在您使用for循环解析数组时我会犹豫是否要操作数组。

我会遍历我的数组,找到位置,然后在循环之外进行拼接:

my $module_index;
for my $spec_index ( 0..$#spec ) {
    my $item = $spec[$spec_index];
    if ( $module =~ /$item/ ) {
        $module_index = $spec_index;
        last;
    }
}
splice (@spec, $module_index, 0, $module);

请注意,我使用0..$#spec来索引我的数组。这样,我不必增加我的 $module_index。无论如何,使用语法不允许$spec_index从循环本身设置值。选择是使用while循环还是使用 C 样式语法:

my $spec_index;
for ( $spec_index = 0; $spec_index <= $#spec; $spec_index++) {
    my $item = $spec[$spec_index];
    last if $module =~ /$item/;
}
splice (@spec, $spec_index, 0, $module);

但是,使用C style for loops被认为是déclassé,或者至少难以维护。根据 Damian Conway(Perl 最佳实践):

Perl 从 C 继承的由三部分组成的 for 语句仅用于不寻常的循环控制行为,例如以两个为单位进行迭代或以不规则的顺序进行迭代。但即使在这种情况下,这些 C 风格的循环也会以一种晦涩难懂且难以维护的方式提供这种不寻常的行为。

有一些方法可以做到这一点,map并且grep需要更少的打字,但我不确定它们是否会更好。您已经有了map的最佳答案,但是您可以查看它并在不经过它的情况下说出它在做什么吗?

问题之一是支持。如果其他人查看您的代码试图弄清楚发生了什么,会发生什么?

于 2013-05-10T19:48:26.133 回答