http://www.perlmonks.org?node_id=39880

dallok has asked for the wisdom of the Perl Monks concerning the following question: (strings)

I have two strings $zero_arg and $sec_arg. I wish to compare each one against a file (routers.txt and interfaceses.txt) respectively. If $zero_arg is a good name then I want it to check the interface name. If $zero_arg is not a good name then DIE.

This is how I have the checking so far. Can I AND two if statements? Such as:

if (grep { $_ eq $zero_arg} @ARRAY) && {$_ ne $sec_arg} @anotherarray) + #Then do command.
Is there some way to make this work like that?

Originally posted as a Categorized Question.

Replies are listed 'Best First'.
Re: How do I compare two strings against two arrays respectively?
by Russ (Deacon) on Nov 04, 2000 at 20:42 UTC
    Yes. You just need to call grep twice (you had incorrect syntax, by leaving off the second grep)
    if (grep {$_ eq $zero_arg} @ARRAY) and not grep {$_ eq $sec_arg} @anot +herarray){ doSomething(); }
    You want to use not (or '!') on the second grep statement (rather than in it (ne) because you want to know if the second array does not contain $sec_arg. What you had would have told you if every line in @anotherarray contained $sec_arg.

    Clear as mud? :-)

    grep is not in void context in this case, because we are testing the scalar value of the array returned by grep. Each grep returns us an array of the lines containing the test string. In scalar context, that becomes the number of elements in that list. If there are no elements in the list, we didn't find the string in @Array, and the statement is false.

    This is not the most CPU-efficient way to accomplish your task, but it is the most PROGRAMMER-efficient way. Weigh the benefits accordingly. If you will be testing for very many strings (in my opinion >1 is enough), you should use one of the other methods (like building a hash, as suggested by runrig).

    Happy grepping!

    P.S. Based on your question, it sounds like, for each string, you want to find it in the first array. If so, then check the second array for that string. If the string does not appear in the first array, die. Right?

    for my $Str ($zero_arg, $sec_arg){ die "$Str is not in routers.txt" unless grep {$_ eq $Str} @Routers; if (grep {$_ eq $Str} @Interfaces){ # The string is a good name, and it appears in @Interfaces # so do something } }
    If you want to know that both strings are good names before you then check both strings against interfaces:
    for my $Str ($zero_arg, $sec_arg){ die "$Str is not in routers.txt" unless grep {$_ eq $Str} @Routers; } if (grep {$_ eq $zero_arg} @Interfaces and grep {$_ eq $sec_arg} @Inte +rfaces){ # They are both there # So do something }
Re: HOw do I compare two strings against to arrays respectively
by Adam (Vicar) on Nov 03, 2000 at 23:30 UTC
    How about something like:
    sub DoubleMatch { my( $item1, $item2, $array_ref1, $array_ref2 ) = @_; for( @$array_ref1 ) { if( $_ eq $item1 ) { for my $item ( @$array_ref2 ) { return 1 if $item eq $item2 } } return 0; } } # Then you can say: if( DoubleMatch( $item1, $item2, \@array1, \@array2 ) { # do stuff }
    Not that I've tested that or anything.
Re: HOw do I compare two strings against to arrays respectively
by quidity (Pilgrim) on Nov 04, 2000 at 00:36 UTC

    Yipee, another chance to use my favourite module... It might not run fast, but it'll be cool!

    use Quantum::Superpositions; my $first = any(@routers); my $second = any(@interfaces); if ( ($first_arg eq $first) and ($second_arg ne $second)) { # .. do stuff .. # }
Re: HOw do I compare two strings against to arrays respectively
by Fastolfe (Vicar) on Nov 04, 2000 at 01:27 UTC
    If we're going against two separate files here, it might not be most efficient to slurp each file up, and do our comparisons against the file's contents. Something like the following might be more efficient:
    sub check_file { my $filename = shift; my $string = shift; open(F, "< $filename") or die "$filename: $!"; while(<F>) { close(F), return 1 if /\Q$string\E/; } close(F); return } if (search_file('file1', 'string1') && search_file('file2', 'string2')) { print "OK\n"; } else { print "No\n"; }
    The question title itself is referring to arrays, in which case the other responses would be more appropriate, but the question itself has to do with file contents, so I thought I'd throw this out there.
      Oops.. I guess that ought to be:
      sub search_file { ...
Re: HOw do I compare two strings against to arrays respectively
by runrig (Abbot) on Nov 04, 2000 at 00:39 UTC
    grep (or map) in a void context is generally considered bad. Better to store the array in a hash, especially if you access it more than once:
    my %file; @routers{@ARRAY} = undef; @interfaces{@anotherarray} = undef if (exists $routers{$zero_arg} and not exists $interfaces{$sec_arg)) { #Do stuff }
      Re-reading your problem (and if I understand it correctly), I'd do it this way:
      my %file; @routers{@ARRAY} = undef; die "Bad zero_arg" unless exists $routers{$zero_arg}; my %interfaces; @interfaces{@anotherarray} = undef; unless (exists $interfaces{$sec_arg)) { #Do stuff } # OR this, if appropriate return if exists $interfaces{$sec_arg}; #Do stuff
Re: How do I compare two strings against two arrays respectively?
by ariels (Curate) on Mar 27, 2001 at 17:43 UTC
    Here's another way to do it, if I correctly understand what you want to do. You want to find an index $i for which $a[$i] eq $a and $b[$i] ne $b (that is, your condition holds at the same index). So why are you searching the array elements? It's better to search for an appropriate index!
    @indices = grep { $a[$_] eq $a and $b[$_] ne $b } (0..$#a);