使用"?"作为一封信的替身

时间:2014-10-04 22:56:14

标签: python pattern-matching wildcard

我写了一个函数来搜索字符串中的模式,但我希望它能够读取"?"任何字母(a-z),例如,模式"?ab?c"将在" xabyc"中找到。我还没有找到答案,但我可能只是在寻找错误的东西。我想通过定义来做到这一点吗?任何字母a-z,不使用正则表达式或类似的东西。 这是我的原始代码:

def main():
    string=input("String")
    pattern=input("Pattern")
    m = match(string, pattern)
    if m==True:
        print ("A perfect match!")
    elif m==False:
        print ("Better try again...")
def match(string, pattern):
    index=0
    while index<=string:
        if string[index:len(pattern)]==pattern:
            return True
        index = index +1
    return False

编辑:意识到整个代码都是错误的,改变了代码的最后部分,它仍然没有工作,我仍然不知道如何制作&#34;?&#34;工作。

def match(string, pattern):
    index= string[0]
    if len(pattern)<=len(string):
        while index<=len(string):   
            if string[index:len(pattern)]==pattern:
                return True
            else:
                index = index +1
        return False

1 个答案:

答案 0 :(得分:1)

如果您想完全避免使用正则表达式并且只需要支持帖子中说明的单个案例,那么这应该有效:

def match(string, pattern):
    if len(string) != len(pattern):
        return False
    for s, p in zip(string, pattern):
        if s != p and p != '?':
            return False
    return True

执行示例:

>>> match('ABC', 'ABC')
True
>>> match('ABC', 'AbC')
False
>>> match('ABC', 'A?C')
True

<强>解释

  1. 您可以迭代一个字符串,每次迭代都会产生另一个字符:

    >>> [i for i in 'ABC']
    ['A', 'B', 'C']
    
  2. zip允许您一起迭代两个列表:

    >>> [(s, p) for (s, p) in zip('STRING1', 'string2')]
    [('S', 's'), ('T', 't'), ('R', 'r'), ('I', 'i'), ('N', 'n'), ('G', 'g'), ('1', '2')]
    

  3. 关于您的代码段的一些评论:

    1. 无需将输入字符串转换为str,因为它们可以保证属于该类型。
    2. 使用True运算符检查Falseis值。正如@PadraicCunningham评论的那样,在这种情况下,只检查if m(没有== Trueis True)就足够了,因为返回的值肯定是True或{{1}但是,我更喜欢明确。有关详细信息,请参阅this
    3. 您的False循环要么永远运行,要么永远运行。您对while的测试不会在整个循环和compares them lexicographically中发生变化。
    4. 当使用切片来访问迭代的一部分时,如果它从0开始,则无需明确提及它,例如, pattern <= string相当于string[0:len(pattern)]
    5. 您已经增加了string[:len(pattern)]变量而没有先将其初始化,并且您不会在其他任何地方使用它。
    6. 之前的评论已不再适用,因为您已更新了代码,但您的新陈述也没有任何意义。 index没有内容支持将Python添加到int,因为它没有明确定义。执行该行代码将引发以下异常:

      str

      此外,即使它返回了一些值,也不能将它设置为>>> 'ABC'+1 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: cannot concatenate 'str' and 'int' objects 对象,因为str对象是不可变的(在下面的示例中,-1表示长度)可迭代减去1):

      str

      使用列表,它可以工作:

      >>> x = 'ABCDE'
      >>> x[1:-1] = '123'
      Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
      TypeError: 'str' object does not support item assignment
      
    7. 之前的评论不再适用,因为您已经再次更新了代码,但该更新也存在缺陷。现在,您要在>>> x = ['A', 'B', 'C', 'D', 'E'] >>> x[1:-1] = [1, 2, 3, 4, 5] >>> x ['A', 1, 2, 3, 4, 5, 'E'] 循环的测试子句中将intstr进行比较。在Python 3中,这将始终引发异常(though, not in Python 2):

      while

    8. 编辑:

      根据您对实际所需行为的评论,这是一个更新的解决方案。简而言之,它与前一个类似,但它使用了>>> 'ABC' > 0 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unorderable types: str() > int() 函数的修改版本,它希望两个输入的长度完全相同。 match从原始match_all变量中提取此类子字符串,并使用每个子字符串以及原始string变量调用match

      pattern

      执行示例:

      def match_all(string, pattern):
          if len(string) < len(pattern):
              return False
          for index in range(0, len(string) - len(pattern) + 1):
              if match(string[index:index + len(pattern)], pattern) is True:
                  return True
          return False
      
      def match(string, pattern):
          for s, p in zip(string, pattern):
              if s != p and p != '?':
                  return False
          return True