为了账号安全,请及时绑定邮箱和手机立即绑定

Python Regex 从内部匹配开始

Python Regex 从内部匹配开始

慕尼黑的夜晚无繁华 2023-02-15 15:18:23
我正在使用 Python 开发一个正则表达式,它将数学表达式转换为 Sympy 语言pow(x,y)中的幂格式。例如,它接受2^3并返回pow(2,3).我目前的模式是:# patternpattern = re.compile(r'(.+?)\^(.*)')为了找到嵌套表达式的数学运算,我使用 for 循环来计算 ^(hat) 的数量,然后使用 re.sub 生成幂格式:# length of the for loopnum_hat = len(re.findall(r'\^', exp))# for nested powfor i in range(num_hat):    exp = re.sub(pattern, r'pow(\1,\2)', exp)return exp此方法不适用于嵌套的 ^ 表达式,例如a^b^c^dorsin(x^2)^3因为最后括号的位置不正确。因为a^b^c^d它返回pow(pow(pow(a,b,c,d)))因为sin(x^2)^3它返回pow(pow(sin(x,2),3))有什么办法可以克服这个问题吗?我尝试了负面前瞻,但它仍然无法正常工作
查看完整描述

3 回答

?
繁华开满天机

TA贡献1816条经验 获得超4个赞

没有很好的说法,但你有一个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


查看完整回答
反对 回复 2023-02-15
?
守候你守候我

TA贡献1802条经验 获得超10个赞

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


一个小演示,


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

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


pow(a,b^c^d)

现在在这种情况下,您的正则表达式将使 part1 成为pow(a,b,而 part2 成为c^d)。因为,用于从 part1 和 part2 构建信息的 pow 语句就像pow(part1, part2),你最终得到的pow( pow(a,b , c^d) )不是你想要的。


查看完整回答
反对 回复 2023-02-15
?
繁花如伊

TA贡献2012条经验 获得超12个赞

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


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)

解释:在有 a 的情况下循环^并替换最后一个匹配项(存在$)


查看完整回答
反对 回复 2023-02-15
  • 3 回答
  • 0 关注
  • 130 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信