python 分割和评估

发布于 2024-11-15 04:36:47 字数 215 浏览 0 评论 0原文

如何将一个字符串(带后缀)拆分为一个带括号的字符串?我的意思是,如果用户输入 3 (3 6 *) * 我希望解释器能够乘以 3 18 * 并理解文本中的括号。这可能吗?类似于 str.split() 但带有开始和结束分隔符?

难道我不现实吗?我发现 shlex 模块类似,但它只引用 AFAIK。

How might I split a string (with postfix) into one with parentheses? What I mean is, if the user inputs 3 (3 6 *) * I want the interpreter to be able to multiply 3 18 * and understand the parentheses in the text. Is this possible? Like a str.split() but with a start and end delimiter?

Am I not being realistic? I found the shlex module similar, but it only does quotes AFAIK.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

谁把谁当真 2024-11-22 04:36:47

我不认为使用 re 是一个坏主意。您可以一次用其运算结果替换嵌套括号。对我来说似乎很简单:

import re
regex = re.compile(r'\([^\(\)]+\)')

def eval_expr(expr):
    match = regex.search(expr)
    if match:
        sub_expr = match.group()
        return eval_expr(expr.replace(sub_expr, str(eval_expr(sub_expr[1:-1]))))
    args = expr.split()
    op = args.pop()
    return eval(op.join(args))

并像这样使用:

>>> eval_expr('(1 (2 3 -) 4 +) (5 6 *) 7 +')
<<< 41

I don't think using re is such a bad idea. You could just go through replacing the nested parenthesis one at a time with the result of their operation. Seems pretty straight forward to me:

import re
regex = re.compile(r'\([^\(\)]+\)')

def eval_expr(expr):
    match = regex.search(expr)
    if match:
        sub_expr = match.group()
        return eval_expr(expr.replace(sub_expr, str(eval_expr(sub_expr[1:-1]))))
    args = expr.split()
    op = args.pop()
    return eval(op.join(args))

And use like so:

>>> eval_expr('(1 (2 3 -) 4 +) (5 6 *) 7 +')
<<< 41
别想她 2024-11-22 04:36:47

我对正则表达式不太熟悉。要求提供这个例子会不会太过分了?

正如克里斯的,呃,各种各样的评论所指出的,你不能有一个(真正的)正则表达式来解析嵌套括号。 (根据他的说法,有一些技巧和扩展可以扩展表达式语言,使其能够解析上下文无关语法。这是我第一次听说,但对我来说这听起来是个坏主意。 )

这个答案似乎也有反对票......还有其他方法可以做到这一点吗?

阅读本文

I'm not very familiar with regular expressions. Would it be too much to ask to ask for an example for this one?

As Chris's, uh, variegated comments indicated, you can't have an (true) regular expression that will parse nested parentheses. (According to him, there are some sort of hacks and extensions that would broaden the expression-language to let it parse context-free grammars. This is the first I've heard of that, but it sounds like a bad idea to me.)

This answer also seems to have downvotes...Are there any other ways to do this?

Read this.

独夜无伴 2024-11-22 04:36:47

您可以编写一个 正则表达式 来提取带括号的子表达式。 re.split 可能会有所帮助,如果什么你关心的是在匹配的括号上分裂。一个简单的正则表达式可以让您挑选出子表达式。

#!/usr/bin/env python
import re
source = r"3 (3 6 *) *"
rewritten = source[:]
match_index = 1
snag_deepest = re.compile(r"""(?P<pre>.*)(?P<sub>\([^()]+\))(?P<post>.*)""")

print "Starting -> %s" % (rewritten)
results = snag_deepest.search(rewritten)
while results is not None:
    print "Subexpression %d -> %s" % (match_index, results.group('sub'))
    rewritten = "%s%s%s" % (results.group('pre'), "sub_%d" % match_index, results.group('post'))
    print "Rewritten as -> %s" % (rewritten)
    results = snag_deepest.search(rewritten)
    match_index += 1

产生

Starting -> 3 (3 6 *) *
Subexpression 1 -> (3 6 *)
Rewritten as -> 3 sub_1 *

You could write a regular expression to extract parenthesized subexpressions. re.split may be helpful if what you care about is splitting on matched parentheses. A straightforward regular expression would let you pick out the subexpressions.

#!/usr/bin/env python
import re
source = r"3 (3 6 *) *"
rewritten = source[:]
match_index = 1
snag_deepest = re.compile(r"""(?P<pre>.*)(?P<sub>\([^()]+\))(?P<post>.*)""")

print "Starting -> %s" % (rewritten)
results = snag_deepest.search(rewritten)
while results is not None:
    print "Subexpression %d -> %s" % (match_index, results.group('sub'))
    rewritten = "%s%s%s" % (results.group('pre'), "sub_%d" % match_index, results.group('post'))
    print "Rewritten as -> %s" % (rewritten)
    results = snag_deepest.search(rewritten)
    match_index += 1

produces

Starting -> 3 (3 6 *) *
Subexpression 1 -> (3 6 *)
Rewritten as -> 3 sub_1 *
节枝 2024-11-22 04:36:47

首先,了解当运算符的元数已知时,后缀表示法中不需要括号。了解原因:

3 3 6 * *

从左侧开始,将操作数堆叠起来,直到遇到运算符:

operands <- 3 <- 3 <- 6
operator: *

我们知道 * 是二元运算符,因此从堆栈中弹出两个操作数,应用运算符,然后将结果推回on:

operands -> 3 -> 6
operands <- 18

继续累积操作数,直到遇到另一个运算符:

operator: *
operands -> 3 -> 18
operands <- 54

当表达式被使用时(假设其格式良好),堆栈将包含一个值:结果。

但你的问题是关于括号的:假设你的愿望是能够解析任意嵌套括号,正则表达式将无法帮助你,原因如下此处。您需要能够识别上下文无关语法的东西,即下推自动机

但我认为,你正在寻找的不仅仅是抽象的计算机科学术语;而是更多的东西。 这里是一个相关问题,其中包含一些关于Shunting Yard 算法,将带括号的中缀表达式转换为后缀表达式。

编辑:好吧,我应该说“true正则表达式单独不会帮助你。”您可以使用正则表达式(匹配最里面的括号对)和替换(实际上)将括号表达式视为其自己的隐式解析树。但调车场算法更酷:)

First, understand that parenthesis are not necessary in postfix notation when the arity of an operator is known. To see why:

3 3 6 * *

Starting from the left, stack operands until you encounter an operator:

operands <- 3 <- 3 <- 6
operator: *

We know that * is a binary operator, so pop two operands off the stack, apply the operator, and push the result back on:

operands -> 3 -> 6
operands <- 18

Continue to accumulate operands until you encounter another operator:

operator: *
operands -> 3 -> 18
operands <- 54

When the expression is consumed (assuming it's well-formed) the stack will contain one value: the result.

But your question is about parenthesis: assuming that your desire is to be able to parse arbitrarily nested parentheses, regular expressions will not help you, for reasons explained here. You need something that can recognize a context free grammar, i.e. a pushdown automaton.

But you're looking, I take it, for something more than abstract computer science-speak; here's a related question that has some useful information on the Shunting Yard Algorithm, which converts parenthesized infix expressions into postfix expressions.

Edit: Ok, I should have said "true regular expressions alone will not help you." You could use regular expressions (matching innermost pairs of parenthesis) and substitution to (in effect) treat a parenthesized expression as its own implicit parse tree. But the Shunting Yard Algorithm is cooler :)

心的位置 2024-11-22 04:36:47

如果我错了请纠正我,但你的表达是 RPD。如果是这样,则实际上不需要使用括号。请在下面找到我的示例(未优化并且很奇怪):

import operator

def rpd_eval(expression):
    if expression.count('(') != expression.count(')'):
        return 0    
    expression = expression.replace(' ', '')
    ops = {'*': operator.mul, '**': operator.pow, '%': operator.mod,
           '+': operator.add, '-': operator.sub, '/': operator.div,
           '^': operator.pow}        
    res = []
    for v in list(expression):
        if not v in ops and v not in ['(',')']:
            res.append(int(v))
        elif v not in ['(',')']:
            b = float(res.pop())
            a = float(res.pop())
            res.append(ops[v](a, b))
    return res[0]

print rpd_eval('3(63*)*5+') # will print 59

Correct me if i am wrong but your expression is the RPD. If so there is no actual need to use parenthesis. Please find my sample(not optimized and weird) below:

import operator

def rpd_eval(expression):
    if expression.count('(') != expression.count(')'):
        return 0    
    expression = expression.replace(' ', '')
    ops = {'*': operator.mul, '**': operator.pow, '%': operator.mod,
           '+': operator.add, '-': operator.sub, '/': operator.div,
           '^': operator.pow}        
    res = []
    for v in list(expression):
        if not v in ops and v not in ['(',')']:
            res.append(int(v))
        elif v not in ['(',')']:
            b = float(res.pop())
            a = float(res.pop())
            res.append(ops[v](a, b))
    return res[0]

print rpd_eval('3(63*)*5+') # will print 59
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文