regex: extract power in calculation

Viewed 257

I need to get a list of powers from an expression, for example:

'2 * x ** 3 + x ** -1 + x**4'

the expected result is

[3, -1, 4]

I have no idea how to do this, hence I cannot include any attempts what what I have tried.


I will be so grateful for any advice

5 Answers

Use this regex '\*\*\s*(-?\d+)' as suggested in the the following code:

>> import re
>> s = '2 * x ** 3 + x ** -1 + x**4'
>> exponents = [int(exponent) for exponent in re.findall('\*\*\s*(-?\d+)', s)]
>>> exponents
[3, -1, 4]

Some explanation about the regex:

\*\* - You need to scape ** because * in regex means any character.

\s* - after ** you might need no white spaces or multiple spaces

(-?\d+) - it will allow you to have positive and negative integers.

[int(m.group(1)) for m in re.finditer('\*\*\s*(-?\d+)', t)]

The regexp here:
\*\* - two asterisks, you need to escape them with backslash as normally they have special meaning
\s* - any number of whitespace characters, unescaped asterisk means "any number"
(-?\d+) - a minus sign which might or might not be there followed one or more digits, the parentheses added so we can reference the content in group(n) query

The rest of it is to make it oneliner - constructing a list from the iterator of matches, casting to integer the part that we are interested in

I used a little more than RegEx, works as well though:

import re

inp_str = '2 * x ** 3 + x ** -1 + x**4'
results = list(map(lambda x:int("".join(x)),re.findall(r"\*\*(-)?(\d+)",inp_str.replace(" ",""))))
print(results)

Use the following code.

[*]{2} - twice asterisks
\s? - space, tab is or not
-? - sign (-) is or not
\d - number

import re

text = '2 * x ** 3 + x ** -1 + x**4'

res = re.findall( r'[*]{2}\s?-?\d', text) ## expected ['** 3', '** -1', '**4']
ans = [int(item[2:].strip()) for item in res] ## expected [3, -1, 4]
print(ans)

You can also use ast.NodeVisitor to walks the abstract syntax tree and calls a visitor function for every node found

>>> source = "2 * x ** 3 + x ** -1 + x ** 4"
>>> import ast
>>> class ExponentsVisitor(ast.NodeVisitor):
...     exponents = []
...     def visit_BinOp(self, node):
...         self.visit(node.left)
...         self.visit(node.right)
...         if isinstance(node.op, ast.Pow):
...             if isinstance(node.right, ast.UnaryOp): # Right hand side is unary operator
...                 self.exponents.append(int(f"-{node.right.operand.value}"))
...             if isinstance(node.right, ast.Constant): # It's a constant.
...                 self.exponents.append(node.right.value)
... 
>>> visitor = ExponentsVisitor()
>>> visitor.visit(ast.parse(source))
>>> print(visitor.exponents)
[3, -1, 4]
Related