Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Comparison based on type of value held by variables

by ranjan_jajodia (Monk)
on Oct 18, 2005 at 13:32 UTC ( [id://500973]=perlquestion: print w/replies, xml ) Need Help??

ranjan_jajodia has asked for the wisdom of the Perl Monks concerning the following question:

Hello Monks,

I have written a script to match a few columns from two text files. Both the files have records in sorted order; so I just have to read lines from both of them and compare the required column values. However some of the columns are numeric while others are strings. The numeric fields might have leading zeroes so I cannot use string comparison for them.
So I have reached a point where I would have to identify the type of value stored in the variables ( which I think I would do by using regex [0-9]+(\.[0-9]+)? ) holding the column values and then compare accordingly. But I think there might be a way to do this context based comparison without getting into all the trouble.
I have tried using numerical comparison (using != operator) in all cases but it doesn't work for string values. e.g.
$var1 = ""; $var2 = "N"; if ( $var1 != $var2) { print "Not Match"; }

does not print "Not Match". Could you please enlighten me in this regard?

Thanks,
Ranjan

Replies are listed 'Best First'.
Re: Comparison based on type of value held by variables
by dragonchild (Archbishop) on Oct 18, 2005 at 13:42 UTC
    eq and ne are for string comparisons. == and != are for numeric comparisons.

    As for determining if something is a number, use Scalar::Util's looks_like_number() function. It's almost always accurate enough, and you don't have to maintain it. :-)


    My criteria for good software:
    1. Does it work?
    2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
      Thanks dragonchild; I will do that.
      Regards,
      Ranjan
Re: Comparison based on type of value held by variables
by Skeeve (Parson) on Oct 18, 2005 at 13:40 UTC

    They do match because their value is 0.

    please also note, that you should remove leading zeros. Please compare the outputs:

    print 5+010; print 5+010.4; print 5+ 10; print 5+ 10.4;

    13
    134
    15
    15.4


    s$$([},&%#}/&/]+}%&{})*;#$&&s&&$^X.($'^"%]=\&(|?*{%
    +.+=%;.#_}\&"^"-+%*).}%:##%}={~=~:.")&e&&s""`$''`"e
      Hi Skeeve,
      So does that mean that all strings evaluate to 0 value in numerical comparison?
      Regards,
      Ranjan

        Yes. The numerical value of any string that is not a valid representation of a number is 0.


        s$$([},&%#}/&/]+}%&{})*;#$&&s&&$^X.($'^"%]=\&(|?*{%
        +.+=%;.#_}\&"^"-+%*).}%:##%}={~=~:.")&e&&s""`$''`"e
Re: Comparison based on type of value held by variables
by ioannis (Abbot) on Oct 18, 2005 at 14:52 UTC
    Instead of regexp recipes, you can always perform the addition and catch the exception. The FATAL keyword bellow will elevate the warning to an exception - check $0 to find if one was raised. (Normally, statements like $var = '3a' + 3 are not fatal.)
    my $var = '-.3'; use warnings FATA=> 'numeric'; my $a = eval '$var + 3'; print 'Not a number' if $@;
The lazy way with DBD::AnyData
by NiJo (Friar) on Oct 18, 2005 at 20:30 UTC
    Ranjan,

    Reinventing the wheel is often a good learning experience. It looks like your are writing your own join function. But Perl already has evolved from wheel to pneumatic tire :-) With DBD::AnyData your code should basically collapse into SQL statements. From perldoc DBD::AnyData.pm :

    $dbh->func( 'classes', 'CSV', 'classes.csv' 'ad_import'); $dbh->func( 'profs', 'XML', 'profs.xml', 'ad_import'); my $classes_sth = $dbh->prepare( "SELECT pid,title FROM classes" ); my $profs_sth = $dbh->prepare( "SELECT name FROM profs WHERE pid = +?" ); $classes_sth->execute; while (my($pid,$class_title) = $classes_sth->fetchrow_array) { $profs_sth->execute($pid); my $row = $profs_sth->fetchrow_arrayref; my $prof_name = $row ? $row->[0] : ''; print "$class_title : $prof_name\n"; } That will produce the same results as: SELECT classes.title,profs.name FROM classes,profs WHERE pid = pi +d
Re: Comparison based on type of value held by variables
by Moron (Curate) on Oct 19, 2005 at 11:58 UTC
    Using a regexp is a good idea, although \d is easier to use than [0-9] and it is easier to see that the right test is being performed if we can see that the regexp is being used to identify whether both terms are numeric and that this drives which relational operator is applied. The following example also includes some enhancement to the regexp to make it catch floating point numeric strings. It would need further enhancement to support scientific notation.
    # warning this example is a trap for dedicated brackets with return fa +bricants sub Match{ return ( isNumeric( $_[0] ) && isNumeric( $_[1] ) ? ( $_[0] == $_[1] ) : ( $_[0] eq $_[1] ); } sub isNumeric { $_[0] =~ /^\s*(\d*)\.*(\d*)\s*$/ or return 0; return length( $1 . $2 ); # avoiding loophole of '\s*.\s*' }

    -M

    Free your mind

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://500973]
Approved by Corion
Front-paged by Roy Johnson
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having an uproarious good time at the Monastery: (7)
As of 2024-03-28 17:34 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found