Multiway Branching

R

rshepard

I need to look at two-byte pairs coming from a machine, and interpret the
meaning based on the relative values of the two bytes. In C I'd use a switch
statement. Python doesn't have such a branching statement. I have 21
comparisons to make, and that many if/elif/else statements is clunky and
inefficient. Since these data are coming from an OMR scanner at 9600 bps (or
faster if I can reset it programmatically to 38K over the serial cable), I
want a fast algorithm.

The data are of the form:

if byte1 == 32 and byte2 == 32:
row_value = 0
elif byte1 == 36 and byte2 == 32:
row_value = "natural"
...
elif byte1 == 32 and byte2 == 1:
row_value = 5
elif byte1 == 66 and byte2 == 32:
row_value = 0.167

There are two rows where the marked response equates to a string and 28
rows where the marked response equates to an integer (1-9) or float of
defined values.

Suggestions appreciated.

Rich
 
J

Justin Azoff

I need to look at two-byte pairs coming from a machine, and interpret the
meaning based on the relative values of the two bytes. In C I'd use a switch
statement. Python doesn't have such a branching statement. I have 21
comparisons to make, and that many if/elif/else statements is clunky and
inefficient. Since these data are coming from an OMR scanner at 9600 bps (or
faster if I can reset it programmatically to 38K over the serial cable), I
want a fast algorithm.

The data are of the form:

if byte1 == 32 and byte2 == 32:
row_value = 0
elif byte1 == 36 and byte2 == 32:
row_value = "natural"
...
elif byte1 == 32 and byte2 == 1:
row_value = 5
elif byte1 == 66 and byte2 == 32:
row_value = 0.167

There are two rows where the marked response equates to a string and 28
rows where the marked response equates to an integer (1-9) or float of
defined values.

Suggestions appreciated.

Rich

Use a dictionary:

byte_values = {
(32,32) : 0,
(36,32) : 'natural',
(32,1 ) : 5,
}

row_value = byte_values[byte1,byte2]
 
J

Justin Azoff

I need to look at two-byte pairs coming from a machine, and interpret the
meaning based on the relative values of the two bytes. In C I'd use a switch
statement. Python doesn't have such a branching statement. I have 21
comparisons to make, and that many if/elif/else statements is clunky and
inefficient. Since these data are coming from an OMR scanner at 9600 bps (or
faster if I can reset it programmatically to 38K over the serial cable), I
want a fast algorithm.

The data are of the form:

if byte1 == 32 and byte2 == 32:
row_value = 0
elif byte1 == 36 and byte2 == 32:
row_value = "natural"
...
elif byte1 == 32 and byte2 == 1:
row_value = 5
elif byte1 == 66 and byte2 == 32:
row_value = 0.167

There are two rows where the marked response equates to a string and 28
rows where the marked response equates to an integer (1-9) or float of
defined values.

Suggestions appreciated.

Rich

Use a dictionary:

byte_values = {
(32,32) : 0,
(36,32) : 'natural',
(32,1 ) : 5,
}

row_value = byte_values[byte1,byte2]
 
F

Fredrik Lundh

I need to look at two-byte pairs coming from a machine, and interpret the
meaning based on the relative values of the two bytes. In C I'd use a switch
statement. Python doesn't have such a branching statement. I have 21
comparisons to make, and that many if/elif/else statements is clunky and
inefficient. Since these data are coming from an OMR scanner at 9600 bps (or
faster if I can reset it programmatically to 38K over the serial cable), I
want a fast algorithm.

The data are of the form:

if byte1 == 32 and byte2 == 32:
row_value = 0
elif byte1 == 36 and byte2 == 32:
row_value = "natural"
...
elif byte1 == 32 and byte2 == 1:
row_value = 5
elif byte1 == 66 and byte2 == 32:
row_value = 0.167

There are two rows where the marked response equates to a string and 28
rows where the marked response equates to an integer (1-9) or float of
defined values.

DATA_MAP = {
chr(32)+chr(32): 0,
chr(36)+chr(32): "natural",
...
chr(32)+chr(1): 5,
chr(66)+chr(32): 0.167,
}

....

row_value = DATA_MAP[source.read(2)]

# or: row_value = DATA_MAP.get(source.read(2), DEFAULT)

</F>
 
B

bearophileHUGS

A dict can be useful:

byte1, byte2 = 32, 1

conv1 = {(32, 32):0, (36,32):"natural", (32,1):5, (66,32):0.167}
print conv1[byte1, byte2]

If you use Psyco maybe something like this can be faster:

conv2 = dict((k1*256+k2,v) for (k1,k2),v in conv1.items())
print conv2[(byte1<<8) + byte2]

conv1/conv2 has to be defined just one time.

Bye,
bearophile
 
B

Bengt Richter

I need to look at two-byte pairs coming from a machine, and interpret the
meaning based on the relative values of the two bytes. In C I'd use a switch
statement. Python doesn't have such a branching statement. I have 21
comparisons to make, and that many if/elif/else statements is clunky and
inefficient. Since these data are coming from an OMR scanner at 9600 bps (or
faster if I can reset it programmatically to 38K over the serial cable), I
want a fast algorithm.

The data are of the form:

if byte1 == 32 and byte2 == 32:
row_value = 0
elif byte1 == 36 and byte2 == 32:
row_value = "natural"
...
elif byte1 == 32 and byte2 == 1:
row_value = 5
elif byte1 == 66 and byte2 == 32:
row_value = 0.167

There are two rows where the marked response equates to a string and 28
rows where the marked response equates to an integer (1-9) or float of
defined values.

Suggestions appreciated.
Set up a dict to map your byte pairs to values, e.g.,
... ((32,32), 0),
... ((36,32), "natural"),
... # ...
... ((32, 1), 5),
... ((66,32), 0.167)
... ])

Then you can access the values like:
'natural'

The .get method allows you to specify a default, in case you get an unexpected pair.
You could also use pairvalues[(byte1,byte2)] and catch the KeyError exception for
unexpected pairs.
... print '%10s => %r' %((byte1,byte2), pairvalues.get((byte1,byte2), 'DEFAULT ??'))
...
(66, 32) => 0.16700000000000001
(32, 1) => 5
(36, 32) => 'natural'
(32, 32) => 0
(20, 20) => 'DEFAULT ??'

HTH

Regards,
Bengt Richter
 
B

Bengt Richter

I need to look at two-byte pairs coming from a machine, and interpret the
meaning based on the relative values of the two bytes. In C I'd use a switch
statement. Python doesn't have such a branching statement. I have 21
comparisons to make, and that many if/elif/else statements is clunky and
inefficient. Since these data are coming from an OMR scanner at 9600 bps (or
faster if I can reset it programmatically to 38K over the serial cable), I
want a fast algorithm.

The data are of the form:

if byte1 == 32 and byte2 == 32:
row_value = 0
elif byte1 == 36 and byte2 == 32:
row_value = "natural"
...
elif byte1 == 32 and byte2 == 1:
row_value = 5
elif byte1 == 66 and byte2 == 32:
row_value = 0.167

There are two rows where the marked response equates to a string and 28
rows where the marked response equates to an integer (1-9) or float of
defined values.

DATA_MAP = {
chr(32)+chr(32): 0,
chr(36)+chr(32): "natural",
...
chr(32)+chr(1): 5,
chr(66)+chr(32): 0.167,
}

...

row_value = DATA_MAP[source.read(2)]

# or: row_value = DATA_MAP.get(source.read(2), DEFAULT)
Much better than my version, since you went beyond the OP's code to what he said
he was trying to do ("look at two-byte pairs coming from a machine ... over the serial cable").
I just went for a direct translation of the code, which is nearly always a mistake.
I should know better. I guess I do, since I always rant about requirements ;-/
Also don't know why I chose to use dict([]) vs {}, since there's no bare key names to
clean the quotes off of. Oh well.

Regards,
Bengt Richter
 
R

rshepard

DATA_MAP = {
chr(32)+chr(32): 0,
chr(36)+chr(32): "natural",
...
chr(32)+chr(1): 5,
chr(66)+chr(32): 0.167,
}
...
row_value = DATA_MAP[source.read(2)]

# or: row_value = DATA_MAP.get(source.read(2), DEFAULT)

Thank you, Fredrik. That's ideal, and a great lesson for a newcomer to
Python.

Rich
 
I

Ivan Voras

inefficient. Since these data are coming from an OMR scanner at 9600 bps (or
faster if I can reset it programmatically to 38K over the serial cable), I
want a fast algorithm.

It depends on your actual environment, of course, but 38kbps is usually
not considered "fast" today - given a modern CPU (or even one from a few
years back), 21 (or 42) short string comparisons in an interprated
language should be trivially fast.

(I'm not saying that using a different approach such as dictionaries
isn't good because of other reasons :) )
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,276
Messages
2,571,384
Members
48,072
Latest member
FaustoBust

Latest Threads

Top