配对的Delimeter匹配

时间:2016-06-17 21:21:47

标签: python stack delimiter

我想编写一个类,当且仅当输入的表达式只包含正确匹配的分隔符(例如" (),<>,[],{}"到目前为止我所写的内容就是这样。

delim_openers = '{([<'
delim_closers = '})]>'

def check_delimiters(expr):
    val = Stack()
    for c in expr:
        if c == (any(x) for x in delim_openers):
            val.push(c)
        elif c == (any(y) for y in delim_closers):
            try:
                val.pop()
            except:
                return False
    return val.empty()

我有点困惑但是如果我针对特定情况(例如下面的情况)测试此情况,当我假设它将返回False时它将返回true,我的堆栈不应该弹出分隔符在这种情况下。测试用例:

from unittest import TestCase
tc = TestCase()
tc.assertFalse(check_delimiters('[ ( ] )'))
tc.assertFalse(check_delimiters('((((((( ))))))'))

我如何编辑`check_delimiters&#39;在这些场景中正确返回False的方法?堆叠的先进先出能力往往会让我感到困惑。此处还有堆栈类代码,以防其他任何事情令人困惑。

class Stack:
    class Node:
        def __init__(self, val, next=None):
            self.val = val
            self.next  = next

    def __init__(self):
        self.top = None

    def push(self, val):
        self.top = Stack.Node(val, self.top)

    def pop(self):
        assert self.top, 'Stack is empty'
        val = self.top.val
        self.top = self.top.next
        return val

    def peek(self):
        return self.top.val if self.top else None

    def empty(self):
        return self.top == None

    def __bool__(self):
        return not self.empty()

    def __repr__(self):
        if not self.top:
            return ''
        return '--> ' + ', '.join(str(x) for x in self)

    def __iter__(self):
        n = self.top
        while n:
            yield n.val
            n = n.next

1 个答案:

答案 0 :(得分:0)

不需要any,简单的包含检查就足够了。然后你必须检查closer是否与opener匹配,否则你只是检查闭门器和开启器的数量是否相等,闭门器是否从不计算领先优势:

class Stack(list):
    push = list.append
    def peek(self):
        return self[-1] if self else None
    # ...

match = dict(zip('{([<', '})]>'))  # dict makes the matching check faster
delim_openers = set(match.keys())  # set makes the 'in' check faster
delim_closers = set(match.values())

def check_delimiters(expr):
    val = Stack()
    for c in expr:
        if c in delim_openers:
            val.push(c)
        elif c in delim_closers:
            try:
                assert match[val.pop()] == c
                # fails if stack is empty or brackets don't match
            except:
                return False
    return not val

> check_delimiters('[ ( ] )')
False
> check_delimiters('[ ( ) ]')
True