如何检查一行文本中是否包含列表中的任意一个字符串?

32

可能是重复问题:
检查一个字符串中是否存在多个子字符串

我想找出一种简洁明了的方法来测试是否存在三个不同的字符串。

基本上,我使用一个for循环遍历一个文件;然后我必须检查它是否包含我在列表中设置的3个字符串中的1个。

到目前为止,我已经找到了多个if条件检查,但感觉并不是特别优雅和高效:

for line in file
    if "string1" in line or "string2" in line or "string3" in line:
        print "found the string"

我想创建一个包含string1string2string3的列表,并检查这些字符串是否都包含在该行中。但似乎不能仅仅比较列表,而是需要显式地循环遍历列表,那么我就会陷入与上面写的多个if语句相同的情况。

有没有更聪明的办法来检查多个字符串,而不必编写冗长的if语句或循环遍历列表元素?


1
你需要搜索每一行还是只找到第一个?如果是后者,你可以通过跳出for循环来进行优化。 - Tyler Crompton
3个回答

77
strings = ("string1", "string2", "string3")
for line in file:
    if any(s in line for s in strings):
        print "yay!"

3
虽然 any 函数的意义相当直观,但我从未使用过它,因此不得不查阅文档。@Niklas 写的很好。 - Brigand
3
这是一个函数。any 的作用是检查序列中是否有任何一个值为 true-ish(真实值)。真正的奇妙在于使用生成器表达式来创建序列。 - Karl Knechtel
@ShankarKumar 我认为只需要一个简单的打印行而不是打印“yay!”就可以了 :) - Pitto
@Pitto:那有什么更简单的方法吗? - Niklas B.
1
@Pitto:啊,我现在才看到你的评论是回复Shabkar的 :) 但是,“line”不是找到的字符串。那将是“string”的匹配元素。 - Niklas B.
显示剩余7条评论

14

代码仍然会遍历这两个列表的笛卡尔积,但这段代码只有一行:

>>> lines1 = ['soup', 'butter', 'venison']
>>> lines2 = ['prune', 'rye', 'turkey']
>>> search_strings = ['a', 'b', 'c']
>>> any(s in l for l in lines1 for s in search_strings)
True
>>> any(s in l for l in lines2 for s in search_strings)
False

这种方法的优点是any会短路,所以一旦找到匹配项,循环就会停止。此外,它仅在linesX中查找search_strings中字符串的第一次出现。如果您想查找多个出现,则可以尝试以下方法:

>>> lines3 = ['corn', 'butter', 'apples']
>>> [(s, l) for l in lines3 for s in search_strings if s in l]
[('c', 'corn'), ('b', 'butter'), ('a', 'apples')]

如果你想编写更复杂的代码,似乎Aho-Corasick算法可以检测给定输入字符串中多个子字符串的存在。(感谢Niklas B.指出这一点。) 我仍然认为对于你的用例来说它会导致二次性能,因为你仍然需要多次调用它来搜索多行。但是,它会战胜上面提到的(平均为立方)算法。


1
实际上是有的。看看Aho-Corasick自动机。它可以在线性时间内完成。 - Niklas B.
@NiklasB.,谢谢,这很有趣!如果我错了,请纠正我,但我认为结果仍然是二次的,因为OP想要测试多行子字符串匹配。但是,这仍然比naive any版本好(立方级别,假设in的平均O(n)性能)。 - senderle
更准确地说,您只需从针构建自动机一次,并将其重复使用于每行。 - Niklas B.
我认为自动机是由针构建的... - senderle
是的,那就是我想表达的意思... - Niklas B.
显示剩余3条评论

4

一种方法是将搜索字符串组合成正则表达式模式,例如这个答案中所示。


我认为正则表达式更美观,但是正则表达式的开销不是很大吗?它真的比一个更简单的“if ... or ... or ...:”更有效吗? - Sam Redway
@SamRedway 有一些额外开销,但另一方面,搜索字符串可以组合成一个模式,在一次处理中完成。 - Janne Karila
@SamRedway 嗯,好的,快速测试表明正则表达式与其他方案相比不够好。 - Janne Karila
1
所以我猜在大多数情况下,可读性比效率更重要,这是基于该指标的完全合理的方法。不过,我会说“更高效”可能会误导。 - Sam Redway
@SamRedway 是的,现在已经编辑掉了。 - Janne Karila

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接