What would be the most efficient way to write the following code in Perl:
my $index = 0;
foreach ( @spec ) {
if ( $module =~ m/$_/ ) {
splice(@spec, $index, 0, $module);
last;
}
$index++;
}
This works fine but just seems a little wordy. The idea is that where I find a match for $module in the array I add an entry. I want to keep the array in a certain order and sorted.
2 Answers 2
You want "more efficient wordiness"??? I presume you're not asking for golfing, but for code that's more readable from conciseness.
@spec = map { $_ eq $module ? ($_, $_) : $_ } @spec;
-
\$\begingroup\$ Yeah this is perfect! \$\endgroup\$evolution– evolution2013年05月10日 15:25:11 +00:00Commented May 10, 2013 at 15:25
You manually increment the
$index
. Just loop over the indices instead:for my $index (0 .. $#spec) { if ($module =~ /$spec[$index]/) { splice @spec, $index, 0, $module; last; } }
On newer perls (v12+) you can use
each
on arrays:use 5.012; while(my ($i, $str) = each @spec) { if ($module =~ /$str/) { splice @spec, $i, 0, $module; keys @spec; # reset the `each` iterator last; } }
If the values in
@spec
are not regexes, but just plain strings, and iff you want to test that$module
contains the string in$spec[$index]
, then you could useindex
for better efficiency.if (-1 != index $module, $spec[$index]) { ... }
This also won't treat characters like
\[]()?+*
as metacharacters any more. This would be similar to/\Q$spec[$index]\E/
(seequotemeta
function), but more efficientIf you actually want to apply the string as a regex, this point is moot.
-
\$\begingroup\$ Ad. #1: I'd use foreach loop and increment counter manyally just like OP, so it's rather subjective (although
each
would be my choice if all production code run on >= v5.12). \$\endgroup\$Grzegorz Rożniecki– Grzegorz Rożniecki2013年05月10日 14:36:08 +00:00Commented May 10, 2013 at 14:36 -
\$\begingroup\$ It would probably be safer to reset the iterator before you modify the array. \$\endgroup\$ikegami– ikegami2013年05月13日 01:12:14 +00:00Commented May 13, 2013 at 1:12