在python中解析嵌套括号,按级别获取内容

jus*_*ess 14 python parsing parentheses

显然,这个问题在阅读之后会经常出现

正则表达式检测用于&while循环的半冒号终止C++

并且思考了一会儿的问题,我写了一个函数来返回包含在任意数量的嵌套()内的内容

该函数可以很容易地扩展到任何正则表达式对象,在此发布您的想法和注意事项.

任何重构建议将不胜感激

(注意,我仍然是python的新手,并且不想弄清楚如何引发异常或其他什么,所以我只是让函数返回'失败',如果它不能弄清楚发生了什么)

编辑功能以考虑评论:

def ParseNestedParen(string, level):
    """
    Return string contained in nested (), indexing i = level
    """
    CountLeft = len(re.findall("\(", string))
    CountRight = len(re.findall("\)", string))
    if CountLeft == CountRight:
        LeftRightIndex = [x for x in zip(
        [Left.start()+1 for Left in re.finditer('\(', string)], 
        reversed([Right.start() for Right in re.finditer('\)', string)]))]

    elif CountLeft > CountRight:
        return ParseNestedParen(string + ')', level)

    elif CountLeft < CountRight:
        return ParseNestedParen('(' + string, level)

    return string[LeftRightIndex[level][0]:LeftRightIndex[level][1]]
Run Code Online (Sandbox Code Playgroud)

Gar*_*ees 29

您没有明确说明您的函数的规范是什么,但这种行为对我来说似乎是错误的:

>>> ParseNestedParen('(a)(b)(c)', 0)
['a)(b)(c']
>>> nested_paren.ParseNestedParen('(a)(b)(c)', 1)
['b']
>>> nested_paren.ParseNestedParen('(a)(b)(c)', 2)
['']
Run Code Online (Sandbox Code Playgroud)

您对代码的其他评论:

  • Docstring说"生成",但函数返回一个列表,而不是生成器.
  • 由于只返回一个字符串,为什么要在列表中返回它?
  • 在什么情况下函数可以返回字符串fail
  • 反复呼叫re.findall,然后丢弃结果是浪费.
  • 您尝试重新平衡字符串中的括号,但一次只能执行一个括号:
>>> ParseNestedParen(')' * 1000, 1)
RuntimeError: maximum recursion depth exceeded while calling a Python object
Run Code Online (Sandbox Code Playgroud)

正如托米在提到的问题中所说的那样,"正则表达式确实是错误的工具!"


解析嵌套表达式的常用方法是使用堆栈,沿着这些行:

def parenthetic_contents(string):
    """Generate parenthesized contents in string as pairs (level, contents)."""
    stack = []
    for i, c in enumerate(string):
        if c == '(':
            stack.append(i)
        elif c == ')' and stack:
            start = stack.pop()
            yield (len(stack), string[start + 1: i])

>>> list(parenthetic_contents('(a(b(c)(d)e)(f)g)'))
[(2, 'c'), (2, 'd'), (1, 'b(c)(d)e'), (1, 'f'), (0, 'a(b(c)(d)e)(f)g')]
Run Code Online (Sandbox Code Playgroud)


Oli*_*çon 5

括号匹配需要具有下推自动机的解析器。存在一些库,但是规则很简单,我们可以从头开始编写它:

def push(obj, l, depth):
    while depth:
        l = l[-1]
        depth -= 1

    l.append(obj)

def parse_parentheses(s):
    groups = []
    depth = 0

    try:
        for char in s:
            if char == '(':
                push([], groups, depth)
                depth += 1
            elif char == ')':
                depth -= 1
            else:
                push(char, groups, depth)
    except IndexError:
        raise ValueError('Parentheses mismatch')

    if depth > 0:
        raise ValueError('Parentheses mismatch')
    else:
        return groups

print(parse_parentheses('a(b(cd)f)')) # ['a', ['b', ['c', 'd'], 'f']]
Run Code Online (Sandbox Code Playgroud)