I have my code like this:
if ( $var eq \"str1\" || $var eq \"str2\" || $var eq \"str3\" )
{
...
}
Is there anyways to optimize this. I want
Use List::MoreUtils qw{any}
use List::MoreUtils qw{any};
if ( any { $var eq $_ } 'str1', 'str2', 'str3' ) {
...
}
This might be faster than using grep
because List::MoreUtils::any
finishes early when it finds a match whereas grep
might build a complete list of matches. I say 'might' because Perl could conceivably optimise if (grep ...
. It might not. But List::MoreUtils::any
does finish early, and it's more descriptive than the if (grep ...
idiom.
Make a hash that has keys of all the strings you want to match
my %matcher;
@matcher{qw{str1 str2 str3}} = ();
if ( exists $matcher{$var} ) {
...
}
This has the disadvantage of a set-up time and the cost of the memory used for the hash, but the advantage is that the match time is more like O(log N). So if you have lots of different values of $var
that you want to test then it could be faster overall.
Make a regex that matches all of your strings
if ( $var =~ m/^str[123]$/so ) {
...
}
OK, so this is fine if your strings are literally qw{str1 str2 str3}
, but what if it is a list of arbitrary strings?
You could use Regexp::Assemble to fuse together a list of regexps into a single optimised regexp.
For a list of fixed strings, convert your list to a hash. This is especially useful if you are going to check against your list several times, and if your list gets larger.
%on_my_list = map {; $_ => 1 } 'str1', 'str2', 'str3', ...;
if ($on_my_list{$var}) { ... }
I'm semi-joking, but this will do it:
use Quantum::Superpositions;
if ($x == any($a, $b, $c)) { ... }
See also this Perl Monks thread
In Perl 5.10 or better:
if ($var ~~ [qw( str1 str2 str3 )]) { ...}
The ~~
operator does a smart match between its arguments.
Depending on the contents of the strings, a regex is quite convenient:
if ($var =~ /^(str1|str2|str3)$/) { … }
Failing that, you can grep over a list:
if (grep { $var eq $_ } qw{str1 str2 str3}) { … }