tags:

views:

351

answers:

3

I don't know if that's the right word for it, but I am trying to come up with some regex's that can extract coefficients and exponents from a mathematical expression. The expression will come in the form 'axB+cxD+exF' where the lower case letters are the coefficients and the uppercase letters are the exponents. I have a regex that can match to both of them, but I'm wondering if I can use 2 regexs, one to match the coefficients and one for the exponents. Is there a way to match a number with a letter on one side of it without matching the letter? EG, in '3x3+6x2+2x1+8x0' I need to get ['3', '6', '2', '8'] and ['3', '2', '1', '0']

+1  A: 
>>> import re
>>> equation = '3x3+6x2+2x1+8x0'
>>> re.findall(r'x([0-9]+)', equation)
['3', '2', '1', '0']
>>> re.findall(r'([0-9]+)x', equation)
['3', '6', '2', '8']
Paolo Bergantino
+5  A: 

You can use positive look-ahead to match something that is followed by something else. To match the coefficients, you can use:

>>> s = '3x3+6x2+2x1+8x0'
>>> re.findall(r'\d+(?=x)', s)
['3', '6', '2', '8']

From the documentation of the re module:

(?=...) Matches if ... matches next, but doesn’t consume any of the string. This is called a lookahead assertion. For example, Isaac (?=Asimov) will match 'Isaac ' only if it’s followed by 'Asimov'.

For the exponents, you can use positive look-behind instead:

>>> s = '3x3+6x2+2x1+8x0'
>>> re.findall(r'(?<=x)\d+', s)
['3', '2', '1', '0']

Again, from the docs:

(?<=...) Matches if the current position in the string is preceded by a match for ... that ends at the current position. This is called a positive lookbehind assertion. (?<=abc)def will find a match in abcdef, since the lookbehind will back up 3 characters and check if the contained pattern matches.

Ayman Hourieh
Nice work. I can't recall having read a better explanation of positive look-ahead/look-behind.
Adam Bernier
+1  A: 

Yet another way to do it, without regex:

>>> eq = '3x3+6x2+2x1+8x0'
>>> op = eq.split('+')
['3x3', '6x2', '2x1', '8x0']
>>> [o.split('x')[0] for o in op]
['3', '6', '2', '8']
>>> [o.split('x')[1] for o in op]
['3', '2', '1', '0']
Adam Bernier