如何检查一个字符串是否包含字母表中的任何字母?

122

最佳纯 Python 实现是什么,用于检查字符串是否包含字母表中的任何字母?

string_1 = "(555).555-5555"
string_2 = "(555) 555 - 5555 ext. 5555

string_1 没有包含字母所以返回 False,而 string_2 包含字母所以返回 True


2
这个应该限制在英文字母A到Z内吗?像德语中的“特殊”字符是否也应该考虑在内? - Kotch
你会收到Unicode编码吗?还是只有普通的ASCII罗马字母? - KobeJohn
时间选择得很好 :) 无论如何,如果您需要帮助测试具有Unicode字符的字符串,请查看此类似问题。 - KobeJohn
1
仅限于英文 a/z 字母表和纯 ascii 罗马字母 :) - papezjustin
7个回答

161

正则表达式应该是一种快速的方法:

re.search('[a-zA-Z]', the_string)

66
正则表达式似乎有点过头了。any(c.isalpha() for c in string_1)非常符合Python风格。 - Jollywatt
11
不是,这个正则表达式比你的表达式易读得多。此外,“isalpha”是什么意思?在比较Python 2和Python 3时,这会产生完全不同的行为。中文是否属于字母表?如果不是,你就是在Python 3(或unicode字符串的Python 2)中盲目地匹配它。如果你想要“Pythonic”,那么这里是:简洁胜于复杂。请查看上面OP的评论:他只想匹配罗马字母。 - JBernardo
1
我认为Joseph的答案非常易读,而且肯定比额外导入更快;此外,您不必记住re.search中参数的顺序。 - Hinton
15
如果有其他人想知道返回值是什么,那么如果匹配成功,你会得到一个“Match”对象;如果没有匹配成功,则返回“None”。所以这与“if re.search(…”的模式兼容。 - Srini
5
从哪个模块导入需要注意,这并不是小事。最好至少提一下。从re模块导入正则表达式操作(适用于Python 2.7到3.9.5)。 - carloswm85
显示剩余5条评论

111

怎么样:

>>> string_1 = "(555).555-5555"
>>> string_2 = "(555) 555 - 5555 ext. 5555"
>>> any(c.isalpha() for c in string_1)
False
>>> any(c.isalpha() for c in string_2)
True

1
@Rik。你的意思是在测试之前将string_1转换为一个集合吗?不,这样做并不会更有效率。我相信any函数在遇到第一个false时就会短路(停止),而这种方法可以保证至少处理所有字符一次。 - KobeJohn
2
@JBernardo:timeit 表明它比编译后的正则表达式慢一个数量级,只比非编译的快大约 66%。这远远在我“讨厌正则表达式”的限度之内。 - DSM
我不知道字符串可能有多大,但函数调用总是很耗费时间的(使用C语言编写的函数,如str.isalpha,调用速度要快得多)。 - JBernardo
2
当然,如果您使用"(555).555-5555 ext. 5555"*1000,由于短路计算,您将回到可比较的速度。我更喜欢用Python编写代码而不是正则表达式,因为我发现除非它们很简单,否则很难调试。除非性能要求需要,否则我不会放弃编写清晰易懂的Python代码。 - DSM
感谢大家的参与/想法/帮助/回答。 - papezjustin
显示剩余3条评论

30
你可以在字符串上使用islower()来查看它是否包含一些小写字母(以及其他字符)。or它与isupper()结合起来,也可以检查它是否包含一些大写字母:
下面: 字符串中的字母为:test,结果为true
>>> z = "(555) 555 - 5555 ext. 5555"
>>> z.isupper() or z.islower()
True

以下内容:字符串"test"中没有字母,结果为false。

>>> z= "(555).555-5555"
>>> z.isupper() or z.islower()
False
>>> 

不要与isalpha()混淆,它仅在所有字符都是字母时返回True,这不是你想要的。

请注意,Barm的答案很好地完成了我的答案,因为我的答案无法很好地处理混合情况。


4
我喜欢这个测试会检查输入是否包含字母,而不仅是检查输入是否全是字母。 - Cornbeetle
@Cornbeetle 是的,经过这么多年,那确实回答了这个问题,谢谢。 - Jean-François Fabre
这是一个非常好的表达方式。就效率而言如何?比正则表达式更好吗? - pnv
没有Python循环参与,因此效率很高。我没有与正则表达式进行比较,但我认为它稍微快一些,特别是在初始化阶段,因为没有需要编译的正则表达式。 - Jean-François Fabre
这会怎么工作?只有当字符串中的所有字符都是大写或小写时,才能起作用。如果存在混合字符,则无法解决此问题... - jrobs585
不处理混合大小写,这在答案中已经说明了。 - Jean-François Fabre

19

我喜欢@jean-françois-fabre提供的答案,但它不完整。
他的方法可以工作,但只有当文本只包含纯小写或大写字母时才有效:

>>> text = "(555).555-5555 extA. 5555"
>>> text.islower()
False
>>> text.isupper()
False

更好的方法是先将您的字符串转换为大写或小写,然后再进行检查。

>>> string1 = "(555).555-5555 extA. 5555"
>>> string2 = '555 (234) - 123.32   21'

>>> string1.upper().isupper()
True
>>> string2.upper().isupper()
False

12

我测试了上述每种查找给定字符串中是否包含任何字母的方法,并发现在标准计算机上每个字符串的平均处理时间。

~250 ns。

import re

~3 微秒

re.search('[a-zA-Z]', string)

~6微秒用于

any(c.isalpha() for c in string)

大约850纳秒用于

string.upper().isupper()

与所说的相反,导入 re 的时间可以忽略不计,并且使用 re 进行搜索所需的时间仅为迭代 isalpha() 约一半,即使对于相对较小的字符串。 因此,对于更大的字符串和更多的计数,re将更高效。 但是,在将字符串转换为大小写并检查大小写(即任何 upper().isupper() lower().islower()之一)时,胜出。它在每个循环中比 re.search()快得多,甚至不需要任何其他导入。

3
您还可以编译正则表达式以进行进一步优化。 alpha_regex = re.compile('[a-zA-Z]')稍后 alpha_regex.search(string) - Behdad Forghani
1
更不用说isalpha()对于多语言的支持并不好。我正在寻找这个方法,因为我想检查一个预期为韩文的字符串是否包含任何英文字母,而isalpha()方法对于每个韩文字符串都返回True。 - Chan Woo

11
你可以使用如下的正则表达式:

你可以像这样使用正则表达式:

import re

print re.search('[a-zA-Z]+',string)

1

你也可以额外做这个

import re
string='24234ww'
val = re.search('[a-zA-Z]+',string) 
val[0].isalpha() # returns True if the variable is an alphabet
print(val[0]) # this will print the first instance of the matching value

还要注意,如果变量val返回None。这意味着搜索没有找到匹配项

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