【问题标题】:Calculate from list of strings - Python [duplicate]从字符串列表计算 - Python [重复]
【发布时间】:2013-07-22 08:00:18
【问题描述】:

我有一个 python 公式,可以将操作数随机放置在数字之间。例如,该列表可能如下所示:

['9-8+7', '7-8-6']

我想要做的是获取每个字符串的值,以便循环遍历字符串,数组将看到 9-8+7 并附加 8,而 7-8-6 将附加 -7。我无法将带有操作数的字符串转换为 int,所以这可能吗?或者我应该改变算法,而不是为每个随机输出创建一个字符串,而是立即计算它的值?

提前谢谢你。

【问题讨论】:

  • 它只是+- 吗?

标签: python string int


【解决方案1】:

您可以对列表项执行eval,但这是一个潜在的安全漏洞,只有在您完全信任来源时才应使用。

>>> map(eval, ['9-8+7', '7-8-6'])
[8, -7]

如果您控制生成字符串的代码,直接计算值听起来是一种更好的方法(更安全,可能更快)。

【讨论】:

    【解决方案2】:

    正如 Fredrik 指出的,您可以在 Python 中执行 eval。我想我会添加一个更通用的方法,它可以在任何语言中使用,并且可能会为那些没有看到它们的人提供一些简单的解析器。

    您正在描述一种语言,其正式定义如下所示:

    expr := sum
    sum := prod [("+" | "-") prod]...
    prod := digit [("*" | "/") digit]...
    digit := '0'..'9'
    

    这个语法(我不会费心做出正确的 EBNF)接受以下字符串:“3”、“4*5/2”和“8*3+9”,等等。

    这为我们提供了如何解析它的线索,而评估只不过是在我们进行过程中累积结果。以下是工作 Python 2 代码。注意代码与语法的紧密程度。

    class ParseFail(Exception):
        pass
    
    def eval_expr(str):
        value, pos = eval_sum(str, 0)
        return value
    
    def eval_sum(str, pos):
        value, pos = eval_product(str, pos)
        accum = value
        while pos != len(str):
            op = str[pos]
            if not str[pos] in ['+', '-']:
                raise ParseFail("Unexpected symbol at position "
                                "{pos} of {str}".format(str=str, pos=pos))
            value, pos = eval_product(str, pos + 1)
            if op == '+':
                accum += value
            else:
                accum -= value
        return accum, pos
    
    def eval_product(str, pos):
        value, pos = eval_digit(str, pos)
        accum = value
        while pos != len(str):
            op = str[pos]
            if not str[pos] in ['*', '/']:
                return accum, pos
            value, pos = eval_digit(str, pos + 1)
            if op == '*':
                accum *= value
            else:
                accum /= value
        return accum, pos
    
    def eval_digit(str, pos):
        if not str[pos].isdigit():
            raise ParseFail("Unexpected symbol at position "
                            "{pos} of {str}".format(str=str, pos=pos))
        return int(str[pos]), pos + 1
    
    try:
        print "3 ->", eval_expr("3")
        print "3*4 ->", eval_expr("3*4")
        print "2+3*4-5 ->", eval_expr("2+3*4-5")
    
        # Should raise ParseFail
        print "2+3*4^2-5 ->", eval_expr("2+3*4^2-5")
    except ParseFail as err:
        print
        print err.args[0]
    

    这是一个示例运行:

    $ python simple_expr.py
    3 -> 3
    3*4 -> 12
    2+3*4-5 -> 9
    2+3*4^2-5 ->
    Unexpected symbol at position 5 of 2+3*4^2-5
    

    很容易将其扩展到具有更多运算符的完整字符串计算器,例如指数运算符'^'和多位整数。括号、浮点数和函数可能需要一些工作,但也不是那么难。在我看来,每个程序员都应该在一生中尝试一次。

    【讨论】:

      【解决方案3】:

      这当然取决于你的表达方式有多好和限制。

      由于减法是负数的加法,您可以将减法写成负数的加法。吐在 + 上以查找条款。然后将总和的项解析为整数,并对它们求和。对每个表达式都这样做。

      [sum(map(int,l.replace('-', '+-').split('+'))) for l in ['9-8+7','7-8-6']]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-09-03
        • 2014-11-01
        • 2018-11-22
        • 2023-03-03
        • 2013-09-10
        相关资源
        最近更新 更多