检查一个字符串是否包含python中相同顺序的另一个字符串的所有单词?

时间:2016-08-31 23:16:04

标签: python string python-2.7 substring

我想检查字符串是否包含所有子字符串的单词并保留其顺序;目前我正在使用以下代码;然而,这是非常基本的,似乎效率低下,并且可能有更好的方法。如果你能告诉我什么是更有效的解决方案,我真的很感激。很抱歉有一个noob问题,我是编程的新手,并且无法找到一个好的解决方案

def check(main, sub_split):
    n=0
    while n < len(sub_split):
        result = True
        if sub_split[n] in main:
            the_start =  main.find(sub_split[n])
            main = main[the_start:]

        else:
            result=False
        n += 1
    return result

a = "I believe that the biggest castle in the world is Prague Castle "
b= "the biggest castle".split(' ')

print check(a, b)

更新:有趣;首先,谢谢大家的回答。还要感谢您指出我的代码遗漏的一些地方。我一直在尝试在这里和链接中发布不同的解决方案,我将添加更新他们如何比较并接受答案。

更新 再次感谢大家提供了很好的解决方案,与我的代码相比,每个解决方案都有了重大改进。我根据我的100000检查要求检查了建议,得到了以下结果; 建议: Padraic Cunningham - 持续不到0.4秒(虽然在搜索完整单词时会产生一些误报; galaxyan - 0.65秒; 0.75秒 友善的狗 - 0.70秒 John1024 - 1.3秒(非常准确,但似乎需要额外的时间)

3 个答案:

答案 0 :(得分:2)

您可以通过将上一场比赛的索引+ 1传递给查找来简化搜索,您不需要切片:

def check(main, sub_split):
    ind = -1
    for word in sub_split:
        ind = main.find(word, ind+1)
        if ind == -1:
            return False
    return True

a = "I believe that the biggest castle in the world is Prague Castle "
b= "the biggest castle".split(' ')

print check(a, b)

如果 ind 曾经 -1 那么你之后就没有匹配,所以你返回False,如果你得到所有的话,那么所有单词都在字符串中

对于确切的单词,您可以使用列表执行类似的操作:

def check(main, sub_split):
    lst, ind = main.split(), -1
    for word in sub_split:
        try:
           ind = lst.index(word, ind + 1)
        except ValueError:
            return False
    return True

要处理标点符号,您可以先将其删除:

from string import punctuation

def check(main, sub_split):
    ind = -1
    lst = [w.strip(punctuation) for w in main.split()]
    for word in (w.strip(punctuation) for w sub_split):
        try:
           ind = lst.index(word, ind + 1)
        except ValueError:
            return False
    return True

当然有些单词对标点符号有效,但这对nltk来说更像是一份工作,或者你可能真的想找到包含任何标点符号的匹配项。

答案 1 :(得分:1)

让我们定义您的a字符串并将您的b字符串重新格式化为正则表达式:

>>> a = "I believe that the biggest castle in the world is Prague Castle "
>>> b = r'\b' + r'\b.*\b'.join(re.escape(word) for word in "the biggest castle".split(' ')) + r'\b'

这将测试b中的单词是否以相同的顺序出现在:

>>> import re
>>> bool(re.search(b, a))
True

警告:如果速度很重要,非正则表达式可能会更快。

如何运作

这里的关键是将字符串重新制作为正则表达式:

>>> b = r'\b' + r'\b.*\b'.join(re.escape(word) for word in "the biggest castle".split(' ')) + r'\b'
>>> print(b)
\bthe\b.*\bbiggest\b.*\bcastle\b

\b仅在字边界处匹配。这意味着,例如,单词the永远不会与单词there混淆。此外,此正则表达式要求所有单词以相同的顺序出现在目标字符串中。

如果a包含与正则表达式b匹配的内容,则re.search(b, a)会返回匹配对象。否则,它返回None。因此,bool(re.search(b, a))仅在找到匹配项时才会返回True

带标点符号的示例

因为单词边界将标点符号视为不是单词字符,所以这种方法不会被标点符号混淆:

>>> a = 'From here, I go there.'
>>> b = 'here there'
>>> b = r'\b' + r'\b.*\b'.join(re.escape(word) for word in b.split(' ')) + r'\b'
>>> bool(re.search(b, a))
True

答案 2 :(得分:-1)

如果您只想检查其他字符串中是否包含单词,则无需全部检查。你只需找到一个并返回true 当你检查项目集更快O(1)(平均值)

a = "I believe that the biggest castle in the world is Prague Castle "
b = "the biggest castle"

def check(a,b):
    setA,lstB = set( a.split() ), b.split() 
    if len(setA) < len(lstB): return False 
    for item in lstB:
        if item in setA:
            return True
    return False

print check(a,b)

如果你不关心速度

def check(a,b):
    setA,lstB = set( a.split() ), b.split() 
    return len(setA) >= len(lstB) and any( 1 for item in lstB if item in setA) 

速度和时间复杂度:link