Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

Trying to compare a string...

by calebcall (Sexton)
on Oct 18, 2013 at 08:02 UTC ( #1058714=perlquestion: print w/ replies, xml ) Need Help??
calebcall has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to compare a string, and for some reason it will always match the first stanza even though it really doesn't. Here's is my compare:

if ($genres[0] eq 'Science Fiction' || 'Sci-Fi' || 'Fantasy') { $genre = 'Sci-Fi & Fantasy'; }elsif ($genres[0] eq 'Action' || 'Adventure' || 'War') { $genre = 'Action & Adventure'; }elsif ($genres[0] eq 'Kids' || 'Family') { $genre = 'Kids & Family'; }else { $genre = $genres[0]; }
Some debug output is:
print "Genres: $genres[0]\n"; print "Genre: $genre\n";
The output looks like:
Genres: Action Genre: Sci-Fi & Fantasy

If I move say Kids & Family to the first block, it always ends up being Kids & Family. Any idea what I'm doing wrong that would cause it to always match that first block?

Comment on Trying to compare a string...
Select or Download Code
Re: Trying to compare a string...
by choroba (Canon) on Oct 18, 2013 at 08:10 UTC
    That's not how || works. The general pattern is
    condition || condition || condition

    So, you have to repeat the whole condition each time:

    if ($genres[0] eq 'Science Fiction' || $genres[0] eq 'Sci-Fi' || or $g +enres[0] eq 'Fantasy') {

    If you think it is a bit verbose, switch to some other way of checking the values:

    # Either if ($genres[0] =~ /^ (?: Science\ Fiction | Sci-Fi | Fantasy ) $/x) { # or if (grep $genres[0] eq $_, 'Science Fiction', 'Sci-Fi', 'Fantasy') {

    etc.

    لսႽ ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Re: Trying to compare a string...
by kcott (Abbot) on Oct 18, 2013 at 08:25 UTC

    G'day calebcall,

    A non-empty string (except '0') will always be TRUE in a boolean context. So, 'Sci-Fi' will always be TRUE. Therefore, even if $genres[0] eq 'Science Fiction' was FALSE, $genres[0] eq 'Science Fiction' || 'Sci-Fi' would always be TRUE, and (with the short-circuiting nature of '||') || 'Fantasy' will never be tested.

    The same will be true for those other conditions. You might want to consider something like this (untested):

    my $genre = $genres[0]; for ($genres[0]) { /^(?:Science Fiction|Sci-Fi|Fantasy)$/ && $genre = 'Sci-Fi & Fanta +sy'; /^(?:Action|Adventure|War)$/ && $genre = 'Action & Adventure'; /^(?:Kids|Family)$/ && $genre = 'Kids & Family'; }

    -- Ken

Re: Trying to compare a string...
by moritz (Cardinal) on Oct 18, 2013 at 08:26 UTC

    In addition to choroba's excellent answer, I'd like to point out that you can replace code with data like this:

    my %genre_map = ( 'Science Fiction' => 'Sci-Fi & Fantasy', 'Sci-FI' => 'Sci-Fi & Fantasy', 'Fantasy' => 'Sci-Fi & Fantasy', 'Action' => 'Action & Adventure', ... ); my $genre = $genre_map{$genres[0]} // $genres[0];

    Factoring the code like this would even allow you to put the genre mapping into a configuration file, and load the hash from it.

    Finally, Perl 6 has a feature called junctions which does allow you to write code similar to what you tried:

    use v6; my $genre; my @genres = 'Kids', 'Ignored'; if @genres[0] eq 'Science Fiction' | 'Sci-Fi' | 'Fantasy' { $genre = 'Sci-Fi & Fantasy'; } elsif @genres[0] eq 'Action' | 'Adventure' | 'War' { $genre = 'Action & Adventure'; } elsif @genres[0] eq 'Kids' | 'Family' { $genre = 'Kids & Family'; } else { $genre = @genres[0]; } say $genre;
Re: Trying to compare a string...
by hdb (Prior) on Oct 18, 2013 at 08:49 UTC

    If you combine kcott's and moritz's answers, you could put the regexes into a hash and then test against that.

    use strict; use warnings; my %genre_table = ( 'Sci-Fi & Fantasy' => qr/Science Fiction|Sci-Fi|Fantasy/, 'Action & Adventure' => qr/Action|Adventure|War/, 'Kids & Family' => qr/Kids|Family/, ); my @genres = ( 'Adventure' ); my( $genre ) = ( ( grep { $genres[0] =~ $genre_table{$_} } keys %genre +_table ), $genres[0]); print $genre;
Re: Trying to compare a string...
by tobyink (Abbot) on Oct 18, 2013 at 10:43 UTC

    There's already been some good answers, but just in the interests of pimping...

    use v5.14; use Switcheroo; my @genres = ('War', 'Death'); my $genre = switch ($genres[0]) do { case "Science Fiction", "Sci-Fi", "Fantasy": "Sci-Fi & Fantasy"; case "Action", "Adventure", "War": "Action & Adventure"; case "Kids", "Family": "Kids & Family"; default: $_; }; say $genre; # Action & Adventure
    use Moops; class Cow :rw { has name => (default => 'Ermintrude') }; say Cow->new->name

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1058714]
Approved by moritz
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chanting in the Monastery: (12)
As of 2015-07-07 12:49 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (88 votes), past polls