如何在Python中检查字符串是否包含列表中的元素

405

我有一个类似这样的东西:

extensionsToCheck = ['.pdf', '.doc', '.xls']

for extension in extensionsToCheck:
    if extension in url_string:
        print(url_string)

我想知道在Python中更优雅的方法是什么(不使用循环)。我想到了这样的方法(从C/C++),但它没有起作用:

if ('.pdf' or '.doc' or '.xls') in url_string:
    print(url_string)

编辑:我有点被迫解释这与下面标记为潜在重复的问题有何不同(所以它不会被关闭,我想)。

区别在于,我想检查一个字符串是否是某些字符串列表的一部分,而另一个问题则是检查来自字符串列表中的字符串是否是另一个字符串的子字符串。类似但不完全相同,语义在你在网上寻找答案时很重要。这两个问题实际上是要解决彼此相反的问题。然而,两者的解决方案都是相同的。


7
可能是Check if multiple strings exist in another string的重复问题。 - GingerPlusPlus
我不确定你最后一段话的意思。你确实想要检查一个字符串列表(文件扩展名)中的一个字符串是否是另一个字符串(URL)的子字符串。 - mkrieger1
8个回答

729

使用生成器以及any一起使用,它会在第一个True值时短路:

if any(ext in url_string for ext in extensionsToCheck):
    print(url_string)

编辑:我看到OP已经接受了这个答案。虽然我的解决方案可能是他特定问题的“足够好的”解决方案,并且是检查列表中任何字符串是否在另一个字符串中找到的一种好的通用方式,但请记住,这就是这个解决方案所做的所有事情。它不关心字符串被发现在哪里,例如在字符串的结尾。如果这很重要,就像在URL中经常发生的情况一样,您应该寻找@Wladimir Palant的答案,否则您可能会出现误报。


5
这正是我正在寻找的。对我来说,在字符串中扩展名出现的位置并不重要。谢谢。 - tkit
1
很好的建议。使用这个例子,我可以检查任何参数是否与众所周知的帮助标志匹配:any([x.lower() in ['-?','-h','--help', '/h'] for x in sys.argv[1:]]) - AXE Labs
8
如果我想知道当 any() 返回 True 时,ext 是什么? - Peter
@PeterSenna:any() 只会返回 true 或 _false_,但请参见 @psun 的列表推导式答案,如下所示:print [extension for extension in extensionsToCheck if(extension in url_string)] - Dannid
谢谢。如果我想从列表中检查并忽略大小写,该怎么办?(包括大写和小写) - Vraj Kotwala
显示剩余3条评论

82
extensionsToCheck = ('.pdf', '.doc', '.xls')

'test.doc'.endswith(extensionsToCheck)   # returns True

'test.jpg'.endswith(extensionsToCheck)   # returns False

8
这个很聪明 - 我不知道元组可以做到这一点!但它只在子字符串锚定于字符串的一端时才有效。 - Dannid
9
太棒了。我只是希望有像“包含”这样的东西,而不仅仅是以某个字符开始或结束。 - BrDaHa
@BrDaHa,你可以使用“in”来判断是否包含。如果列表中有“string”: - Shekhar Samanta
7
@ShekharSamanta 当然可以,但这并没有解决如何检查一个字符串中是否包含多个内容的问题,而这正是原始问题所涉及的。 - BrDaHa
1
在这种情况下,我们可以使用以下代码:如果列表中的任何元素在字符串中(使用任何分隔符拆分字符串),则返回True;对于字符串,如果列表中的任何元素在其中,则返回True。 - Shekhar Samanta

29

最好正确解析URL-这样您就可以正确处理http://.../file.doc?foohttp://.../foo.doc/file.exe

from urlparse import urlparse
import os
path = urlparse(url_string).path
ext = os.path.splitext(path)[1]
if ext in extensionsToCheck:
  print(url_string)

9
如果您想要一个单行解决方案,可以使用列表推导式。以下代码返回一个包含url_string的列表,当它具有扩展名.doc、.pdf和.xls时,或者在不含扩展名时返回空列表。
print [url_string for extension in extensionsToCheck if(extension in url_string)]

注意:这只是用来检查是否包含某些内容,不适用于想要提取与扩展名完全匹配的单词。


这比“任何”解决方案更易读,在我看来,这是该问题的最佳解决方案之一。 - Dmitry Verhoturov
1
在我看来,这个解决方案比any()更优越,因为它可以被修改以返回特定的匹配值,例如:print [extension for extension in extensionsToCheck if(extension in url_string)](请参阅我的答案以获取附加详细信息以及如何从url_string中提取匹配的单词和模式)。 - Dannid

9

如果有人再次遇到这个任务,以下是另一种解决方案:

extensionsToCheck = ['.pdf', '.doc', '.xls']
url_string = 'file.doc'
res = [ele for ele in extensionsToCheck if(ele in url_string)]
print(bool(res))
> True

5
这是@psun提供的列表推导式答案的变体。
通过改变输出值,你实际上可以从列表推导式中提取匹配模式(这在@Lauritz-v-Thaulow的any()方法中不可能)。
extensionsToCheck = ['.pdf', '.doc', '.xls']
url_string = 'http://.../foo.doc'

print([extension for extension in extensionsToCheck if(extension in url_string)])

['.doc']`

如果您希望在确定匹配模式后收集其他信息,可以插入正则表达式(当允许的模式列表太长而无法写入单个正则表达式时这可能非常有用)。

print([re.search(r'(\w+)'+extension, url_string).group(0) for extension in extensionsToCheck if(extension in url_string)])

['foo.doc']


嗨@Dannid。当我尝试你的解决方案时,我得到了一个指向“for”的语法错误。也许自从你发帖以来,Python已经更新了一些需要不同语法的内容?希望你能帮助我。谢谢。 - user2382321
@user2382321,是的,我用Python2写的。Python3需要在print语句中加括号。我已经更新了我的示例代码。 - Dannid

4

检查它是否与该正则表达式匹配:

'(\.pdf$|\.doc$|\.xls$)'

注意: 如果您的扩展名不在URL的末尾,请删除$字符,但这会稍微削弱它。

1
这是一个URL,如果它有查询字符串怎么办? - Wladimir Palant
导入re模块 在你的字符串中搜索匹配模式 - juankysmith
1
虽然这个答案适用于指定的情况,但它不具有可扩展性或通用性。你需要为每个要匹配的模式编写长正则表达式。 - Dannid

1
这是我能想象到的最简单的方法 :)
list_ = ('.doc', '.txt', '.pdf')
string = 'file.txt'
func = lambda list_, string: any(filter(lambda x: x in string, list_))
func(list_, string)

# Output: True

此外,如果有人需要保存字符串中的元素,他们可以使用类似以下代码:

list_ = ('.doc', '.txt', '.pdf')
string = 'file.txt'
func = lambda list_, string: tuple(filter(lambda x: x in string, list_))
func(list_, string)

# Output: '.txt'

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