2 回答
TA贡献1946条经验 获得超4个赞
你的问题有两个层次的答案:(1)解决你当前的问题;(2) 解决您的一般问题。
(1) 非常简单 - 通常用于进行字符串模式匹配和替换的最常见、最通用的工具是正则表达式(RE)。您只需定义您正在寻找的模式、您想要的模式,然后将您的字符串传递给 RE 引擎。Python 有一个内置的RE 模块,称为re. 大多数语言都有类似的东西。某些语言(例如 Perl)甚至将其作为语言语法的核心部分。
模式是一系列特定字符或非特定(“通配符”)字符。因此,在您的情况下,您需要特定 '!' 之前的非特定字符。特点。您似乎建议“之前”在您的情况下表示所有非空白字符,或者如果前面的字符是 ')',则该字符与前面的 '(' 之间的所有字符。所以让我们构建该模式,从没有括号的版本开始:
[\w] - the set of characters which are letters or numbers (we need a set of
characters that doesn't include whitespace or ')' so I'm taking some
liberty to keep the example simple - you could always build your own
more complex set with the '[]' pattern)
+ - at least one of them
! - the '!' character
然后是带括号的版本:
\( - the literal '(' character, as opposed to the special function that ( has
. - any character
+ - at least one of them
? - but dont be "greedy", ie. only take the smallest set of characters that
match the pattern (will work out to be the closest pair of parentheses)
\) - the closing ')' character
! - the '!' character
然后我们只需要把它们放在一起。我们|用来匹配第一个模式或第二个模式。我们使用(和)来表示我们想要“捕获”的模式部分——它是 '!' 之前的那一点。以及我们稍后要使用的括号内。所以你的模式变成:
([\w]+)!|\((.+?)\)!
别担心,RE 表达式总是看起来像是有人刚刚捣碎了键盘。有一些很棒的工具,比如RegExr,可以帮助分解复杂的 RE 表达式。
最后,您只需要获取捕获并将它们粘贴到“math.factorial”中即可。\x表示第xth 场比赛。如果第一个模式匹配,\2则为空白,反之亦然,因此我们可以同时使用它们。
math.factorial(\1\2)
就是这样!这里是如何在 Python 中运行 RE 的(注意r字符串阻止 Python 尝试将其\作为转义序列进行处理):
import re
re.sub(r'([\w]+)!|\((.+?)\)!', r'math.factorial(\1\2)', '2*x + (2x + 1)! - math.sin(x) + 2!')
re.sub采用三个参数(加上一些此处未使用的可选参数):RE 模式、替换字符串和输入字符串。这产生:
'2*x + math.factorial(2x + 1) - math.sin(x) + math.factorial(2)'
这是我相信你所追求的。
现在,(2)更难了。如果您真的打算实现一个以字符串作为输入的计算器,那么您很快就会被正则表达式淹没。在可以输入的内容和 Python 可以解释的内容之间会有很多例外和变化,最终你会得到一些非常脆弱的东西,在第一次与用户接触时就会失败。如果您不打算拥有用户,那么您就非常安全 - 您可以坚持使用有效的模式。如果不是,那么您会发现模式匹配方法有点限制。
一般来说,您要解决的问题称为词法分析(或者更全面地,作为词法分析、句法分析和语义分析的三个步骤过程)。解决这个问题的标准方法是使用一种称为递归下降解析的技术。
有趣的是,Python 解释器在解释上述re语句时执行的正是这个过程——编译器和解释器都执行相同的过程,将字符串转换为可由计算机处理的标记。
你会在网上找到很多教程。它比使用 RE 稍微复杂一些,但允许更广泛的泛化。您可能想从这里的非常简短的介绍开始。
TA贡献1835条经验 获得超7个赞
您可以删除括号并以线性形式计算所有内容,这样在解析括号时它将评估操作数,然后应用阶乘函数 - 按照写入的顺序。
或者,您可以获得
!
字符串中阶乘的索引,然后如果之前索引处的字符是一个)
右括号,您就知道在应用 math.factorial() 之前需要计算一个括号内的操作数。
添加回答
举报