Reputation: 169
Hi Stack overfloweans,
I am finding a value in an array which is a constant allowed_value. If the main_value equals any of the values in allowed_value array, then I am printing the message 'Allowed value is correct'. So I have done the following piece of code.
use constant allowed_value => qw(value1 value2);
my $main_value = 'value2';
my @attr = (allowed_value);
print "Allowed value is correct" if grep $_ eq $main_value, @attr;
Is there any way to make the code better and simplify the code ? Please help. Thanks in advance
Upvotes: 1
Views: 341
Reputation: 193
Depending on how large your file is, i would use if (exists) and map the array into a hash. Once wrote a programm with a lot of greps, took ours to run through 400k lines, when i replaced most of the greps, came down to under 20 seconds.
Upvotes: 0
Reputation: 165198
grep
is fine for small sets, but it has to search the whole set every time.
For larger sets you can do this a bit faster using List::Util's any() function. This has the advantage over grep
that it will stop searching when it matches once. Assuming random data, on average you'll search half the list.
use strict;
use warnings;
use v5.10;
use List::Util 'any';
use constant allowed_values => qw(value1 value2);
my $main_value = 'value3';
say "Good" if any { $_ eq $main_value } allowed_values;
However, that still searching through even part of allowed_values
every time. This is inconsequential for small sets of allowed values, but when it gets large it can get slow.
Instead use a hash as a set. It's a bit more work to set up, but it's more convenient and will perform the same no matter how large the set.
use strict;
use warnings;
use v5.10;
use constant allowed_values => {
value1 => 1, # any true value will do
value2 => 1,
};
my $main_value = 'value2';
say "Good" if allowed_values->{$main_value};
And if your list of allowed values is long, you can generate the hash from a list avoiding a bunch of typing.
use constant allowed_values => {
map { $_ => 1 }
qw(value1 value2)
};
The downside is "constant" references aren't really constant. Only the reference is constant, the contents of that reference can be changed.
allowed_values->{foo} = 42; # this is "fine"
If that's a concern, use Const::Fast instead.
use strict;
use warnings;
use v5.10;
use Const::Fast qw(const);
const my %allowed_values => (
map { $_ => 1 }
qw(value1 value2)
);
my $main_value = 'value2';
say "Good" if $allowed_values{$main_value};
Unless you really need an inlined constant, and generally you don't.
Upvotes: 4