【问题标题】:Regex Split string of arithmetic expression into list with its operators and numbers (decimal included)正则表达式将算术表达式字符串拆分为列表及其运算符和数字(包括十进制)
【发布时间】:2017-08-07 04:06:48
【问题描述】:

我已经编写了这段代码,但我认为这不是最好的方法。

import re
notation = "41*(5.5+6-(8/2^3)-7)-1"
n2 = [x[0] for x in re.findall(r"(\d+(\.\d+)?)",notation)]
n2.reverse()
m = []
x = True

for z in notation:
    if z.isdigit() and x:
        m.append(n2.pop())
        x = False
    if not z.isdigit() and z != ".": 
        m.append(z)
        x = True

预期的输出是:

m = ['41', '*', '(', '5.5', '+', '6', '-', '(', '8', '/', '2', '^', '3', ')', '-', '7', ')', '-', '1']

我认为这段代码有一种硬编码,我的疑问是如何以更好的方式制作它?

【问题讨论】:

    标签: python regex list arithmetic-expressions


    【解决方案1】:

    使用正则表达式 findall,您可以获得您想要的结果!

    正则表达式:

    re.findall('[0-9.]+|.',m)
    

    因此,

    >>> import re
    >>> notation  = '41*(5.5+6-(8/2^3)-7)-1'
    >>> m = re.findall('[0-9.]+|.',notation )
    >>> print m
    ['41', '*', '(', '5.5', '+', '6', '-', '(', '8', '/', '2', '^', '3', ')', '-', '7', ')', '-', '1']
    

    如果您对自己的符号 +\-*^/() 有特别的了解,那么您可以使用

    >>> m = re.findall('[0-9.]+|[+\-*^/()]',notation)
    >>> print m
    ['41', '*', '(', '5.5', '+', '6', '-', '(', '8', '/', '2', '^', '3', ')', '-', '7', ')', '-', '1']
    

    会给你想要的结果!

    希望对你有帮助!

    【讨论】:

    • 正则表达式中的. 将捕获所有内容,甚至是非算术字符,因此如果您的字符串具有例如?! 它将被捕获,这就是我特意制作的原因一个字符类 [+\-*^/()] 而不是 .
    • 我已添加编辑!在第一种情况下,任何符号和数字都将匹配到一个列表,而在第二种情况下,仅限于匹配指定的那些。
    【解决方案2】:

    这是使用re.finditer 的一种方法,使用this re 表达式:

    >>> import re
    >>> m =[]
    >>> s = "41*(5.5+6-(8/2^3)-7)-1"
    >>> for match in re.finditer(r'[+\-*^/()]|[0-9.]+', s):
            if match:
                m.append(match.group(0))
    
    
    >>> m
    ['41', '*', '(', '5.5', '+', '6', '-', '(', '8', '/', '2', '^', '3', ')', '-', '7', ')', '-', '1']
    

    【讨论】:

    • 优秀的答案!我觉得这样更好看:m = [mt.group(0) for mt in re.finditer(r'[+\-*^/()]|([0-9.]+)', s)]
    • @NapoleónCortés,由你决定,我只是为了你的理解而把它简单化了,但我想知道是否因为我没有看到任何 cmets 而被否决? :-O
    • 我投了 +1 票,但我的个人资料没有足够的级别来计算,我不知道你为什么会投反对票:O
    【解决方案3】:

    re.findall 与旨在查找数字运算符的正则表达式一起使用。

    • 数字模式是[0-9.]+,它获取所有数字和小数点。
    • 单字符运算符模式是[*/+\-\^],它可以进行乘法、除法、加法、减法(因为- 是一个特殊的正则表达式字符而被转义)和指数(也因为- 是一个特殊的正则表达式字符而被转义) .

    例如:

    >>> import re
    >>> notation = "41*(5.5+6-(8/2^3)-7)-1"
    >>> re.findall(r'[0-9.]+|[*/+\-\^]', notation)
    ['41', '*', '5.5', '+', '6', '-', '8', '/', '2', '^', '3', '-', '7', '-', '1']
    

    数字模式可以进一步细化以查找最多一位小数。 (?:[0-9]+\.[0-9]+)|(?:[0-9]+\.)|(?:\.?[0-9]+)。这样可以解析3.14 + 42. + .707 + 6中的数字。

    要处理多字符运算符,请将它们放在链中的第一个位置(以防止单个字符先匹配)。例如,(?:\*\*|\*|/|\+|\-) 将解析 2 ** 5 / 6 + 7 * 3 - 1 中的运算符。

    希望这可以帮助您进行词法分析器实验 :-)

    【讨论】:

    • 谢谢!有用的信息,唯一的是我还需要“()”字符。
    猜你喜欢
    • 2012-02-09
    • 1970-01-01
    • 2017-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多