Python разделить и оценить - PullRequest
1 голос
/ 14 июня 2011

Как можно разбить строку (с постфиксом) на строку с круглыми скобками?Я имею в виду, что если пользователь вводит 3 (3 6 *) *, я хочу, чтобы интерпретатор мог умножить 3 18 * и понимать скобки в тексте.Это возможно?Как str.split(), но с начальным и конечным разделителями?

Я не реалистичный человек?Я обнаружил, что модуль shlex похож, но он использует только кавычки AFAIK.

Ответы [ 5 ]

3 голосов
/ 14 июня 2011

Я не думаю, что использование 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))

И использовать вот так:

1 голос
/ 14 июня 2011

Я не очень знаком с регулярными выражениями.Было бы слишком много просить попросить привести пример для этого?

Как указали разнообразные комментарии Криса, у вас не может быть (истинного) регулярного выражения, которое будет анализировать вложенные скобки,(По его словам, существуют некие хаки и расширения, которые расширили бы язык выражений, чтобы он мог анализировать контекстно-свободные грамматики. Это первое, что я слышал об этом, но для меня это звучит как плохая идея.)

Этот ответ также имеет отрицательные голоса ... Есть ли другие способы сделать это?

Чтение это .

0 голосов
/ 14 июня 2011

Поправь меня, если я ошибаюсь, но твое выражение лица - РПД.Если это так, то нет необходимости использовать круглые скобки.Пожалуйста, найдите мой образец (не оптимизированный и странный) ниже:

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
0 голосов
/ 14 июня 2011

Во-первых, поймите, что скобки не нужны в постфиксной нотации, когда известна арность оператора. Чтобы понять почему:

3 3 6 * *

Начиная слева, складывать операнды, пока не встретите оператора:

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

Мы знаем, что * является бинарным оператором, поэтому вытолкните два операнда из стека, примените оператор и верните результат обратно:

operands -> 3 -> 6
operands <- 18

Продолжайте накапливать операнды, пока не встретите другого оператора:

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

Когда выражение используется (при условии, что оно правильно сформировано), стек будет содержать одно значение: результат.

Но ваш вопрос касается скобок: если вы хотите иметь возможность произвольного разбора вложенных скобок, регулярные выражения не помогут вам, по причинам, объясненным здесь . Вам нужно что-то, что может распознавать контекстно-свободную грамматику , то есть автомат с нажатием .

Но вы, я так понимаю, ищете что-то большее, чем просто абстрактную информатику; здесь - это связанный вопрос, в котором содержится некоторая полезная информация по алгоритму Shunting Yard , который преобразует инфиксные выражения в скобках в постфиксные выражения.

Редактировать : Хорошо, я должен был сказать " true регулярные выражения один не поможет вам". Вы можете использовать регулярные выражения (соответствующие самым внутренним парам круглых скобок) и подстановку, чтобы (фактически) обрабатывать выражение в скобках как свое собственное неявное дерево разбора. Но алгоритм «Маневрового двора» круче:)

0 голосов
/ 14 июня 2011

Вы можете написать регулярное выражение , чтобы извлечь заключенные в скобки подвыражения.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 *
...