0

Lets say I have an mapping, map, which associates various strings to numerical values :

{['a', 1],['b', 2], ['c',5]}

I want to define an operation, op, which will distribute over arithmetic operations. So I want op to function as follows:

op('a+b') = 3

op('b') = 2

op('a*b+c') = 7 

etc.

The only way I could think to do it is simply to parse the string, remember the operations, do the mapping, and do the operations. Seems sorta costly/long and I would hope there could be a more elegant solution with a built-in operation.

EDIT:

I realize the way I phrased this wasn't quiet accurate to my question, the mapping isn't defined on my system so I cannot define all possible mappings. I have to query an outside source for the mappings.

Roger Hampton
  • 71
  • 1
  • 5

4 Answers4

1

'not sure that you have in mind but Python allow you to override operators. If parsing a string is not desirable, you might create a wrapper class and define the relevant operators to extract the values from your "mapping". Here, I use a dictionary and I define only the "addition":

class V:
    values = { 'a': 1, 'b': 2, 'c': 3 }

    def __init__(self, name):
        self.name = name

    def __add__(self, other):
        return V.values[self.name] + V.values[other.name]

a = V('a')
b = V('b')

print a+b
# display 3

If you work with strings, you may even eval such expression (even if eval is not your best friend from a security point of view -- you should never directly eval an expression coming from untrusted source):

print eval("a+b")
# display 3
Sylvain Leroux
  • 50,096
  • 7
  • 103
  • 125
0
def op(eqn_str,**vars):
    for var,val in vars.items():
        eqn_str = eqn_str.replace(var,str(val))
    return eval(eqn_str)

op('a+b',a=5,b=3)
op('a+b',**{'a':5,'b':3})
my_vars = {'a':5,'b':3}
op('a+b',**my_vars)

or slightly more interesting

def op(eqn_str,**vars):
    eqn_str = re.sub('(a-z)','%(\\1)s',eqn_str)
    eqn_str = eqn_str.format(vars)
    return eval(eqn_str)
#called same way as above

something like that maybe ... although eval is always a little sketchy

really I second Jon's comment that you should probably look at sympy

to figure out what keys you need you can just do

needed_keys = [letter for letter in str_eqn if letter.isalpha()]
Joran Beasley
  • 110,522
  • 12
  • 160
  • 179
  • -1 for eval I assume ... well yeah it is kinda bad form ... but Im not gonna write up a whole grammar thats for a different post ... – Joran Beasley Jun 21 '13 at 17:49
0

well, except if what you want is to reinvent sympy (see the comment), what you have to do is parse the data in your string, create an abstract syntax tree, get the symbols and transform it to python objects. That way you can even respect operators' priority, and YOU'RE NOT USING EVAL.

My best advice for you would be to look at this 70 lines gist that shows how to implement a simple calculator (somehow what you want). You'll only have to match your values with the ones in the string.

In the same spirit as what I'm talking about, @JFSebastian linked a post that's even better.

Community
  • 1
  • 1
zmo
  • 24,463
  • 4
  • 54
  • 90
0

Here is a one-liner:

>>> eval('b', dict([['a', 1],['b', 2], ['c',5]]))
2
>>> eval('a+b', dict([['a', 1],['b', 2], ['c',5]]))
3
>>> eval('a*b+c', dict([['a', 1],['b', 2], ['c',5]]))
7
User
  • 14,131
  • 2
  • 40
  • 59