Python string processing based on the numeric part: '5a+6b' + '2a+3b+9c' = '7a+9b+9c'
I need to add two simple polynomials (represented as strings). The following example would clarify my requirement.
input1 = '5a+6b'
input2 = '2a+3b+9c'
The required sum should be as follows:
'7a+9b+9c'
Currently I have created a function (of 20 lines) to perform this task for me, but I think this can开发者_运维问答 be improved.
EDIT: Adding my code
def add_domain_strings():
input_list = ['5a+6b', '2a+3b+9c']
vars_dict = {}
for input in input_list:
temp_list = input.split('+')
for i in temp_list:
split_index = None
for j in i:
if not j.isdigit():
split_index = i.index(j)
break
if i[split_index:] in vars_dict:
vars_dict[i[split_index:]] += int(i[:split_index])
else:
vars_dict[i[split_index:]] = int(i[:split_index])
sum_string = ''
for k,v in vars_dict.iteritems():
if sum_string:
sum_string += '+%s%s' % (v,k)
else:
sum_string += '%s%s' % (v,k)
return sum_string
sympy does close to what you want
>>> import sympy
>>> a,b,c = sympy.symbols('abc')
>>> 5*a+6*b + 2*a+9*b+9*c
7*a + 9*c + 15*b
You could either use sympy:
>>> import sympy
>>> from sympy import *
>>> a = Symbol('a')
>>> b = Symbol('b')
>>> c = Symbol('c')
>>> eval('5*a+6*b')
5*a + 6*b
>>> eval('5*a+6*b') + eval('2*a+3*b+9*c')
7*a + 9*b + 9*c
Or write a simple parser:
>>> input1 = '5a+6b'
>>> input2 = '2a+3b+9c'
>>> s = "+".join((input1, input2))
>>> s
'5a+6b+2a+3b+9c'
>>> d = {}
>>> for i in s.split("+"):
... d[i[-1]] = d.get(i[-1], 0) + int(i[:-1])
...
>>> d
{'a': 7, 'c': 9, 'b': 9}
>>> "+".join("".join((str(j),i)) for i, j in d.items())
'7a+9c+9b'
For python2.7+
>>> from collections import Counter
>>> input1 = '5a+6b'
>>> input2 = '2a+3b+9c'
>>> c=Counter()
>>> for inp in input1, input2:
... c+=Counter({x[-1]:int(x[:-1]) for x in inp.split('+')})
...
>>> '+'.join("%s%s"%(v,k) for k,v in sorted(c.items()))
'7a+9b+9c'
It depends on what types of expressions you want to support. If there are to be parenthesis and other constructs, this turns into standard expression parsing - lexical analysis and syntactic analysis. You can just construct appropriate abstract syntax tree and provide suitable rules for evaluation.
Not knowing what you've already got, I'll just post a description of how I would approach this:
- Convert each input to a dictionary on the form
{'a': 5, 'b': 6}
1 - Iterate the dictionary of
input2
and add values to the corresponding key ininput1
- Convert dictionary back to string.
1) The following could be used (assumption: single letters):
d = {}
for e in input1.split("+"):
d[e[:-1]] = e[-1]
if you are willing to sacrifice a bit of speed for a massive control gain, I'd suggest regular expressions:
from re import findall
def make_poly(s):
m = findall('([+-]?[0-9.]+)([a-z]+)', s)
return dict([(i[1], float(i[0])) for i in m])
def add_polys(*polys):
res = {}
for poly in polys:
for item in poly.iteritems():
if res.has_key(item[0]):
res[item[0]] += item[1]
else:
res[item[0]] = item[1]
return res
>>> p1 = make_poly('4x+7y+3.5z')
>>> p1
{'y': 7.0, 'x': 4.0, 'z': 3.5}
>>> p2 = make_poly('-2x+1y+0.2z')
>>> p2
{'y': 1.0, 'x': -2.0, 'z': 0.2}
>>>
>>> add_polys(p1, p2)
{'y': 8.0, 'x': 2.0, 'z': 3.7}
It still needs some tinkering for edge-cases and mal-formed user input but it works so far
精彩评论