Python 正则表达式从内部匹配开始



我正在研究Python中的一个正则表达式,它将数学表达式转换为Sympy语言pow(x,y(中的幂格式。例如,它采用2^3并返回pow(2,3)

我目前的模式是:

# pattern
pattern = re.compile(r'(.+?)^(.*)')

为了找到嵌套表达式的数学,我使用 for 循环来计算 ^(hat( 的数量,然后使用 re.sub 生成幂格式:

# length of the for loop
num_hat = len(re.findall(r'^', exp))
# for nested pow
for i in range(num_hat): 
exp = re.sub(pattern, r'pow(1,2)', exp)
return exp

此方法不适用于嵌套的 ^ 表达式(如a^b^c^dsin(x^2)^3(,因为最后一个括号的位置不正确。

对于a^b^c^d,它返回pow(pow(pow(a,b,c,d)))

对于sin(x^2)^3,它返回pow(pow(sin(x,2),3))

有什么方法可以克服这个问题吗?我尝试了负面的展望,但它仍然不起作用

没有好的说法,但你有一个极端的XY问题。您显然想要的是将一些数学表达式转换为SymPy。编写自己的正则表达式似乎是一种非常乏味、容易出错且可能不可能的方法。

作为一个庞大的符号库,SymPy 附带了一个完整的解析子模块,它允许您详细调整解析表达式,特别是convert_xor控制^字符会发生什么。但是,您似乎不需要执行任何操作,因为将^转换为幂是默认设置。因此,您可以简单地执行以下操作:

from sympy import sympify
print( sympy.sympify("a^b^c^d") )    # a**(b**(c**d))
print( sympy.sympify("sin(x^2)^3") ) # sin(x**2)**3

请注意,**等同于pow,所以我不确定你为什么坚持后者。如果您需要一个可以用另一种编程语言工作的输出,这就是打印模块的用途,并且自己更改它相对容易。另一件可以帮助您获得所需表格的事情是sympy.srepr.

你为什么不为此使用递归?它可能不是最好的,但如果嵌套功率不是很多,它将适用于您的用例,

一个小示范,

import re
#Your approach
def func(exp):
# pattern
pattern = re.compile(r'(.+?)^(.*)')

# length of the for loop
num_hat = len(re.findall(r'^', exp))

# for nested pow
for i in range(num_hat):  # num_hat-1 since we created the first match already
exp = re.sub(pattern, r'pow(1,2)', exp)
return exp

#With recursion
def refined_func(exp):
# pattern
pattern = '(.+?)^(.*)'

# length of the for loop
num_hat = len(re.findall(r'^', exp))

#base condition
if num_hat == 1:
search = re.search(pattern, exp)
group1 = search.group(1)
group2 = search.group(2)

exp = "pow("+group1+", "+group2+")"
return exp

# for nested pow
for i in range(num_hat):  # num_hat-1 since we created the first match already
search = re.search(pattern, exp)
if not search: # the point where there are no hats in the exp
break
group1 = search.group(1)
group2 = search.group(2)

exp = "pow("+group1+", "+refined_func(group2)+")"

return exp
if __name__=='__main__':

print(func("a^b^c^d"))

print("###############")

print(refined_func("a^b^c^d"))

上述程序的输出是,

pow(pow(pow(a,b,c,d)))                                                                                                                
###############                                                                                                                       
pow(a, pow(b, pow(c, d))) 

您的方法中存在的问题:

最初,您从以下表达式开始,

a^b^c^d

使用您定义的正则表达式,上述表达式由两部分组成 -> part1:a和 part2:b^c^d。有了这两个,您可以生成pow(a,b^c^d).所以你使用的下一个表达式是,

pow(a,b^c^d)

在这种情况下,现在,您的正则表达式将给出 part1 作为pow(a,b部分,并将 part2 设为c^d).由于用于从第 1 部分和第 2 部分构造信息的 pow 语句就像pow(part1, part2)一样,您最终会得到pow( pow(a,b , c^d) )这不是您想要的。

我尝试了您的示例,但我仍然建议您找到一个数学解析器(来自我的评论(,因为这个正则表达式非常复杂。

import re

pattern = re.compile(r"(w+((.+))?)^(w+((.+))?)([^^]*)$")

def convert(string):
while "^" in string:
string = pattern.sub(r"pow(1, 3)5", string, 1)
return string
print(convert("a^b^c^d"))  # pow(a, pow(b, pow(c, d)))
print(convert("sin(x^2)^3"))  # pow(sin(pow(x, 2)), 3)

说明:在有^时循环并替换最后一个匹配项(存在$(

最新更新