更清洁的方式写下面的内容

时间:2013-05-10 12:45:24

标签: perl

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

3 个答案:

答案 0 :(得分:5)

你想要“更有效率的话语”???我认为你不是要求打高尔夫球,而是要求更易读的代码。

@spec = map { $_ eq $module ? ($_, $_) : $_ } @spec;

答案 1 :(得分: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 );
    }
}

答案 2 :(得分: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风格的循环也会以一种模糊和难以维护的方式提供这种不寻常的行为。

有些方法可以通过mapgrep执行此操作,这样可以减少输入,但我不确定它们是否会更好。您已经使用map获得了最佳答案,但是您可以查看它并告诉它而不通过它正在做什么吗?

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