我想检查字符串是否包含所有子字符串的单词并保留其顺序;目前我正在使用以下代码;然而,这是非常基本的,似乎效率低下,并且可能有更好的方法。如果你能告诉我什么是更有效的解决方案,我真的很感激。很抱歉有一个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秒(非常准确,但似乎需要额外的时间)
答案 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