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

String comparison in an array

by newperlbie (Acolyte)
on Aug 08, 2018 at 08:37 UTC ( #1220084=perlquestion: print w/replies, xml ) Need Help??
newperlbie has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I have the following code:
.... .... for (....) { push @keys,$key; } my (@elements) = split ';',$line; if ((grep { $elements[0] eq '$_' }@keys)) { print "found"; }
$elements[0] is present in the array @keys, but this code is not matching them, what am I missing? is it something to do with string comparison with quotes and no quotes?

Replies are listed 'Best First'.
Re: String comparison in an array
by haukex (Canon) on Aug 08, 2018 at 08:44 UTC
    grep { $elements[0] eq '$_' }@keys
    is it something to do with string comparison with quotes and no quotes?

    Yes, because single quotes don't interpolate variables - '$_' means "the string consisting of the two characters $ and _". "$_" would interpolate the variable into the string. Note that if @keys contains only strings, you can just say grep { $elements[0] eq $_ } @keys, without the quotes.

    Also, note that grepping an array like this is usually less efficient than using a hash. For example, you can say my %keyhash = map {($_=>1)} @keys; and this will create a hash where the keys are the elements of the @keys array, and the values are all 1. Then, to check if an element is contained in @keys/%keyhash, you just need to say if ($keyhash{$elements[0]}) ....

    Update: The trick with creating a hash that makes it more efficient is of course to only do it once, above any loops. Also, as a side note, there is first from List::Util, that is like grep but stops when it finds the first match (but depending on the data it's likely still slower than a hash).

      sure,thanks,but with hash too the comparison is not working, probably because $element[0] is coming with double quotes "computer" and the strings in the array/hash do to get rid of this, this is coming from the split statement

        It seems you can simply add double quotes around computer, or you can remove double quotes around "computer";

Re: String comparison in an array
by Eily (Prior) on Aug 08, 2018 at 08:43 UTC

    You can add some debug information in your grep while testing, like this:

    grep { print $elements[0], '$_', "\n"; $elements[0] eq '$_' } @keys;
    The issue is that simple quotes prevent interpolation (ie, perl will keep the content unmodified). A bare $_ should do the trick

      In addition to all other suggestions, I recommend that you use the function "any" (from List::Utils) rather than grep. The name makes your intention clear. It can also be slightly faster because it shortcuts after the first match.
      thanks, but bare $_ also did not work printing them gives this : $elements[0] = "computer" $_ = computer

        Ah right, it really looks like you are trying to read a csv file. You should consider using Text::CSV as it already handle special cases (values with quotes among values without, multiline values etc...). Beyond that you can follow hippo's advice

Re: String comparison in an array
by LanX (Archbishop) on Aug 08, 2018 at 09:18 UTC
    Please provide some sample data to reproduce your problem.

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

      2018-08-11 Athanasius restored original content:

      use strict; use warnings; use Data::Dump; use Text::CSV; use List::MoreUtils qw{ any }; my $first = 'computer'; my $last = 'printer'; my $in = 0; my @keys; open DATA, "types.txt" or die $!; while (<DATA>) { if (defined(my $key = (split)[-5])) { if ($key eq $first .. $key eq $last) { $in = 1; push @keys, $key; } elsif ($in && $key eq $last) { push @keys, $key; } else { $in = 0; } } } dd @keys; my $filename = "orders.csv"; my $csv = Text::CSV->new ( { binary => 1 } ); open my $fh, "<:encoding(Latin-1)", "orders.csv" or die "Cannot open $ + +filename"; my $do_skip_test = 1; my %keyhash = map {($_=>1)} @keys; while(my $line = <$fh>) { if ($do_skip_test) { my (@fillarr1) = split ';',$line; #print $fillarr1[14]; #if ((grep { print $fillarr1[14], $_,"\n";$fillarr1[14] eq $_ ++}@keys)) #need to change this loop to compare all array variables #if (($fillarr1[14] =~ /tm_C40_ANA_v1.12.0/) || ($fillarr1[14] + + =~ /tm_C40_ANA_v1.14.0/)) #if (exists $fillarr1{$fillarr1[14]}) #if ($keyhash{$fillarr1[14]}) if (($fillarr1[14] =~ /$_/)@keys) { #$do_skip_test = 0; my (@fillarr) = split ';',$line; print "\n$fillarr[0]\t$fillarr[1]\t$fillarr[3]\t$fillarr[4 + +]\t$fillarr[5]\t$fillarr[14]\t"; } else { next; } } } close($fh);
        That's code not data.

        Please have a look at Data::Dumper (or better Data::Dump if installed) to print your data.

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1220084]
Approved by haukex
Front-paged by Corion
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others browsing the Monastery: (3)
As of 2018-12-11 00:54 GMT
Find Nodes?
    Voting Booth?
    How many stories does it take before you've heard them all?

    Results (52 votes). Check out past polls.

    • (Sep 10, 2018 at 18:53 UTC) Welcome new users!