0

I have a device which outputs several values that normally look like the following:

-1.6410,0.5390,0.5570
-1.6160,0.3860,0.5620
-1.4890,-0.0760,0.5260
-1.4120,-0.1740,0.5290
-1.2920,-0.2160,0.6110
-1.2520,-0.2510,0.6450
-1.2530,-0.2270,0.6330
-1.2670,-0.2220,0.6530
-1.2350,-0.2250,0.7170
-1.4470,-0.3840,0.2400
-1.2670,-0.7480,0.0630
-1.0690,-0.9340,-0.1400
-0.9440,-1.0000,-0.2440

The three numbers may be of any length, and may be positive or negative. Is there a way (in Python) to check that valid numbers were returned rather than a text string (like "CHECKSUM ERROR" or the like)? I don't know what text errors may be received, so I'd like to try to verify that numbers were received. Is this possible?

I had considered a simple IF statement for each variable, but that seems clumsy. For example:

if (value1 > -9999) and (value1 < 9999):
...

I'd have to do this for each of the three values. Is there a simpler way?

Alligator
  • 691
  • 3
  • 11
  • 21

2 Answers2

2

You could pass each line though a regular expression

import re

valid_pattern = re.compile('-?\d\.\d+,-?\d\.\d+,-?\d\.\d+')

for line in lines:
    if valid_pattern.match(line):
        x,y,z = map(float(line.split(","))
    else:
        pass #ignore the line, maybe print a warning whatever
sirlark
  • 2,187
  • 2
  • 18
  • 28
  • You can even make the regular expression do basic bounds checking, e.g. if the diget before the decimal point can only be 0 or 1, then use `-?[01]\.\d+` – sirlark Jul 18 '14 at 21:21
  • What does this do? -?\d\.\d+ – Alligator Jul 18 '14 at 21:31
  • I'm assuming you are either not familiar with regular expressions in general, or the python specific syntax. If the former, a regular expression is a string with special (varies from language to language) describing a pattern that string can match. If you're not familiar with the python syntax, see https://docs.python.org/2/library/re.html for a full description, but I'll describe my regexp "-?\d\.\d+,-?\d\.\d+,-?\d\.\d+". You can see the section "-?\d\.\d+" is repeated. Each repeat describes a floating point number. -? -> optional minus sign (? means preceding character is optional) – sirlark Jul 18 '14 at 21:40
  • \d -> any digit from 0 to 9; \. means a period (. without the backslash matches any single character); \d+ -> one or more digits (0-9) (+ means one or more of the preceding character) – sirlark Jul 18 '14 at 21:40
  • Thanks, I guess I was not familiar with regular expressions. I really appreciate you taking the time to explain this. – Alligator Jul 18 '14 at 21:47
  • No problem... now the trick is to learn when NOT to use them. They tend to become a hammer for all nails type of tool because they are so versatile and flexible. – sirlark Jul 18 '14 at 22:17
1

The solution can be simple: try getting the values, and if it fails (throwing some predicted exception), take it as invalid entry and ignore it.

lines = """
-1.6410,0.5390,0.5570
-1.6160,0.3860,0.5620
-1.4890,-0.0760,0.5260
-1.4120,-0.1740,0.5290
-1.2920,-0.2160,0.6110
-1.2520,-0.2510,0.6450
-1.2530,-0.2270,0.6330
-1.2670,-0.2220,0.6530
-1.2350,-0.2250,0.7170
-1.4470,-0.3840,0.2400
-1.2670,-0.7480,0.0630
BAD GUY WAS HERE
-1.0690,-0.9340,-0.1400
-0.9440,-1.0000,-0.2440
"""

for line in lines.strip().split("\n"):
    try:
        x, y, z = map(float, line.split(","))
        # continue processing here
        print x, y, z
    except ValueError:
        print "I do not like this line", line
        continue
Jan Vlcinsky
  • 42,725
  • 12
  • 101
  • 98
  • @LucasScott Note, that comparing to regular expression solution, this one with simple try - except is faster. And in Python, it is quite common pattern (which allows keeping the code simple, fast and readable). – Jan Vlcinsky Jul 18 '14 at 22:10