3

I'll be brief so I don't waste your time;

Simple problem, i have an array of say, hundreds of dogs

my @dogs = qw(Shepard Lab Dalmation Husky Chow Pitbull ...)

and i want to compare it to a single dog

my $doggy = "Shepard";

pretty stupid i know, but how would i do that?

# Regex match against array?
# (This doesnt even work but its how i would think of doing it)
if ($doggy =~ /@dogs/) {
print $doggy;
}

Thanks for any answers in advance, I appreciate you guys helping me with what is probably a really stupid question. Thank you

3

7 Answers 7

5

I would do it like this :

my %hDogs = map { $_ => 1 } @dogs;

if(exists($hDogs{$doggy})) { ... }
Sign up to request clarification or add additional context in comments.

4 Comments

Okay so convert the 'master dog list' to a Hash, and use that if-exists statement to see if its in the hash, thanks for the answer I was wondering if i should use hash's or not
@user1058357 There is more than 10 ways to do this :)
Hehe, must be pretty bad if i can only think of 1 that doesnt work :P
@user1058357 We have all been through that. Don't let it get to you.
4

You can just use grep:

my @dogs = qw(Shepard Lab Dalmation Husky Chow Pitbull);
my @wanted_dogs = grep {/^Shepard$/} @dogs;
print "@wanted_dogs\n";

Result:

Shepard

The regex can be changed as wanted, and if you're only interested in the first matching dog, you'll find that in $wanted_dogs[0].

2 Comments

Thank you, this answer is helpful as well
My pleasure. It's what grep was made for, and it does it well.
3

Smart match operator:

use warnings;
use strict;

my @dogs = qw(Shepard Lab Dalmation Husky Chow Pitbull);
my $doggy = "Shepard";
if ($doggy ~~ @dogs) {
    print $doggy;
}

Comments

2

Assuming you don't really want a regular expression match and just want to see if there is an exact match somewhere in the list, then you have a number of options.

Smart match is the relatively new, but simplest and possibly fastest approach.

The classic methods are grep and List::Util::first. You can adjust the latter two to use a regex instead of eq if you do want to (for example) match "Shepard" when $dog is "Shep".

use strict;
use warnings;
use v5.10;

my @dogs = qw(Shepard Lab Dalmation Husky Chow Pitbull);
my $dog = "Shepard";
my $cat = "Ocicat";

say "Smart match";
say $dog ~~ @dogs;
say $cat ~~ @dogs;

say "Grep";
say grep { $_ eq $dog } @dogs;
say grep { $_ eq $cat } @dogs;

say "List::Util";
use List::Util qw/first/;
say first { $_ eq $dog } @dogs;
say first { $_ eq $cat } @dogs;

2 Comments

Thanks for the input, any advice is appreciated not sure what method ill be using at this point
Use smart match unless you have an out of date Perl that you can't upgrade (in which case use List::Util).
1

There are techniques using the newer smart-match operator, but I prefer the old classic:

my $dogs_re = join '|' => map quotemeta, @dogs;

if ($doggy =~ /$dogs_re/) {...}

That creates a regex alternation of your dog types, after quoting any regex special characters in the names.

You could compile the regex as well if you want:

$_ = qr/$_/ for $dogs_re;  

which would be placed after the line defining $dogs_re, and may offer some performance benefits if you will be using the regex many times.

5 Comments

This is a little hard to wrap my mind around, but im sure its a great solution, ill read it a few hundred more times :P, thank you for the response
Ahh ok i understand, itd be the equivalent of a regex with multiple match options : (Shepard|Husky|Chow), and then it could execute a regex statement, this is really useful as i will be re-using the regex hundreds of times and need to have it compiled for speed, Thanks much.
@user1058357 : Think about using a module that optimizes such regexes. Regexp::Assemble comes to mind
@Zaid => Starting with 5.9.2, Perl's regex engine will automatically optimize chained alternations like this into a trie.
$dogs_re = qr/$dogs_re/ is shorter and more comprehensible, imho.
0

I would probably choose the hash lookup solution for best answer, but there are many ways to do this. This is one of them.

Note that this uses our dog name as the regex and iterates it over the list instead of the other way around.

use v5.10; # needed for say
@dogs=qw(Shepherd Lab Poodle Foo Bar); 
$dog = 'Lab'; 
/\Q$dog\E/i and say for @dogs;"

You can control how strict the match is:

/\Q$dog\E/i is least strict, ignore case, match anywhere in word. E.g. "lab" will match "Yellow Lab", "Labrador" etc.

/^\Q$dog\E$/ is most strict, match case, match entire word.

Comments

0

Try this,

$" = "|";
my @dogs=qw(Shepherd Lab Poodle Foo Bar);
my $temp = "@dogs";
my $dog = "Lab";
print "$1 found" if ($dog =~ /($temp)/);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.