[英]Check if a string contains all words of another string in the same order python?
我想检查一个字符串是否包含所有子字符串的单词并保留其顺序; 目前,我正在使用以下代码; 但是,这是非常基本的,似乎效率很低,并且可能有更好的方法来执行此操作。 如果您能告诉我什么是更有效的解决方案,我将不胜感激。 很抱歉遇到一个菜鸟问题,我是编程新手,无法找到一个好的解决方案
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秒(非常准确,但似乎要花费额外的时间)
您可以通过传递上一个匹配项的索引+ 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而言,这是一项更大的工作,否则您可能实际上希望查找包含任何标点符号的匹配项。
让我们定义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中的单词是否以相同的顺序出现在a中:
>>> 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
如果您只想检查其他字符串中是否包含一个单词,则无需全部检查。 您只需要找到一个并返回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)
速度和时间复杂性: 链接
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.