Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to split algebraic expressions in a string using python?

Tags:

python

regex

For example I get following input:

-9x+5x-2-4x+5

And I need to get following list:

['-9x', '5x',  '-2',  '-4x', '5']

Here is my code, but I don't know how to deal with minuses.

import re
text = '-3x-5x+2=9x-9'
text = re.split(r'\W', text)
print(text)

warning: I cannot use any libraries except re and math.

like image 807
Micheal Fox Avatar asked Nov 20 '19 11:11

Micheal Fox


3 Answers

You could re.findall all groups of characters followed by + or - (or end-of-string $), then strip the + (which, like -, is still part of the following group) from the substrings.

>>> s = "-9x+5x-2-4x+5"
>>> [x.strip("+") for x in re.findall(r".+?(?=[+-]|$)", s)]
['-9x', '5x', '-2', '-4x', '5']

Similarly, for the second string with =, add that to the character group and also strip it off the substrings:

>>> s = '-3x-5x+2=9x-9'
>>> [x.strip("+=") for x in re.findall(r".+?(?=[+=-]|$)", s)]
>>> ['-3x', '-5x', '2', '9x', '-9']

Or apply the original comprehension to the substrings after splitting by =, depending on how the result should look like:

>>> [[x.strip("+") for x in re.findall(r".+?(?=[+-]|$)", s2)] for s2 in s.split("=")]
>>> [['-3x', '-5x', '2'], ['9x', '-9']]

In fact, now that I think of it, you can also just findall that match an optional minus, followed by some digits, and an optional x, with or without splitting by = first:

>>> [re.findall(r"-?\d+x?", s2) for s2 in s.split("=")]
[['-3x', '-5x', '2'], ['9x', '-9']]
like image 65
tobias_k Avatar answered Nov 11 '22 11:11

tobias_k


One of many possible ways:

import re

term = "-9x+5x-2-4x+5"

rx = re.compile(r'-?\d+[a-z]?')
factors = rx.findall(term)
print(factors)

This yields

['-9x', '5x', '-2', '-4x', '5']
like image 4
Jan Avatar answered Nov 11 '22 11:11

Jan


For your example data, you might split on either a plus or equals sign or split when asserting a minus sign on the right which is not at the start of the string.

[+=]|(?=(?<!^)-)
  • [+=] Match either + or =
  • | Or
  • (?=(?<!^)-) Positive lookahead, assert what is on the right is - but not at the start of the string

Regex demo | Python demo


Output for both example strings

['-9x', '5x', '-2', '-4x', '5']
['-3x', '-5x', '2', '9x', '-9']
like image 1
The fourth bird Avatar answered Nov 11 '22 11:11

The fourth bird