2015-12-26 3 views
2

Это регулярное выражение проблема топала меня ...Split, если не в квадратных скобках

Я хочу, чтобы разбить строку на использование одного из четырех основных математических операций (+, -, /, *), если не ему существует в скобках.

Full: 
'x^2 * ln(sin(x^2 + y^2)) + 8^(2*9)' 

Full Goal: 
['x^2', 'ln(sin(x^2 + y^2))', '8^(2*9)'] 

Simplified Problem: 
'x^2 * sin(x^2 + y^2) + 8^(2*9)' 

Simplified Goal: 
['x^2', 'sin(x^2 + y^2)', '8^(2*9)'] 

Решения либо полная или упрощенная задача будет работать.

+1

Что делать, если скобки имеют глубину более одной глубины? –

+0

@AvinashRaj Хороший улов. Я неправильно скопировал свою проблему из своей IDE. Я отредактировал вопрос, чтобы отразить истинную проблему. – lnNoam

+1

, тогда этот вопрос не разрешается с использованием модуля re-re по умолчанию. –

ответ

2

Regex не может быть использован для надежного решения проблемы. Вместо этого рассмотрите использование очень простой машины состояний, в которой вы отслеживаете, находитесь ли вы внутри фигурных скобок, чтобы определить, следует ли делиться на математическом операторе. Вот очень быстрая попытка, которая, похоже, работает для вашего ввода.

math_ops = {'+', '-', '*', '/'} 

def parse(inval): 
    groups = [] 
    braces = 0 
    part = '' 
    for c in f: 
     # We add to braces count 
     if c == '(': 
      braces += 1 
     # We subtract from braces count 
     elif c == ')': 
      braces -= 1 
     # If we are at a math symbol and our brace count is 0, we have a complete part. 
     if c in math_ops and braces == 0: 
      groups.append(part.strip()) 
      part = '' 
      continue 
     part += c 
    if part: 
     groups.append(part) 
    return groups 

Для двух ваших примеров выход:

['x^2', 'ln(sin(x^2 + y^2))', ' 8^(2*9)'] 
['x^2', 'sin(x^2 + y^2)', ' 8^(2*9)'] 
1

Упрощенная проблема

def split(string): 
    return re.findall(r'(?:[^+\-*/]|\(.*\))+', string) 

Вы не упоминаете зачистки пространства, но ваш пример делает. Если это желательно,

def split(string): 
    return re.findall(r'(?!)(?:[^+\-*/]|\(.*\))+(?<!)', string) 

Полная проблема

Это классический пример не- regular language, т.е. не вычислит конечный автомат, который является то, что регулярные выражения. Вообще говоря, если элементы могут быть вложенными (например, с помощью parens), регулярное выражение является недостаточной моделью вычислений. Вам нужен pushdown automaton или полноценный полный язык Turing, такой как Python.

def split(string): 
    results = [] 
    depth = 0 
    result = '' 
    for c in string + '+': 
     if c == '(': 
      depth += 1 
     elif c == ')': 
      depth -= 1 
     elif not depth and c in {'+', '-', '*', '/'}: 
      results.append(result.strip()) 
      result = '' 
      continue 
     result += c 
    return results 
+0

FYI, вам нужно добавить символ в случай попадания скобки, или скобки отделяются от сегментов в результатах. – sberry

+1

И не быть педантичным, но на Python 'str' нет метода' trim() '. Метод, который вы ищете, это 'strip()' – sberry

+0

@sberry, вы правы; Благодарю. –

Смежные вопросы