开发者

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:

  1. Convert each input to a dictionary on the form {'a': 5, 'b': 6} 1
  2. Iterate the dictionary of input2 and add values to the corresponding key in input1
  3. 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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜