是否有更好的方法来判断字符串是否包含数字?
是否有更好的方法来判断字符串是否包含数字?
我正在处理同时包含数字和字母数字字符,或仅包含数字字符的字符串,但不仅仅是字母字符的字符串。为了测试是否存在错误匹配,我需要检查字符串是否至少包含一个数字字符,如果没有,则打印错误消息。我一直在使用以下代码:
s = '0798237 sh 523-123-asdjlh' def contains_digits(s): for char in list(s): if char.isdigit(): return True break return False if contains_digits(s) == True: print s else: print 'Error'
有没有更Pythonic或更简单的方法来实现这个功能,或者这样足够了?另外,我不能仅仅检查字符串是否是字母数字的,因为字符串可能包含各种符号('-',空格等)。
问题的出现原因:作者想要找到一种更好的方法来判断一个字符串是否包含数字。
解决方法:使用`any`函数,传入一个序列。如果序列中的任何元素为真(即是数字),则`any`函数返回True,否则返回False。
以下是使用`any`函数来判断字符串是否包含数字的代码:
def contains_digits(s): return any(char.isdigit() for char in s)
如果对性能有所担忧,那么当前的方法实际上是更快的。然而,不幸的是,在这种特殊情况下,这种方法的速度只有正则表达式的一半。
感谢提供了`any`函数的信息。所以看起来Python字符串是可迭代的,`for char in s`会遍历字符串中的每个字符。
确实,Python字符串也是序列。
感谢展示了基准测试。我从来没有想过正则表达式甚至可以超过像这样未经优化的代码的性能。我没有考虑性能的问题 - 如果我考虑了,我就会避免使用`any`函数,并使用类似我将要在我的帖子中编辑的代码,这个代码的性能比正则表达式解决方案要好(在32位Python 2.6上的Win7上比正则表达式解决方案快约1.062比1.254)。
实际上,我曾经预期`any`函数和这个代码的性能是一样快的。
更新了基准测试的结果。只有当字符串中的第一个数字早早被找到时,`if`语句和`isdigit`函数的组合才能与正则表达式的解决方案相竞争。
这是有道理的。我之前不知道正则表达式会这么快!虽然这是有道理的,因为这个解决方案花费的时间都在执行C代码,而不是在解释器和库代码之间的混合。基准测试总是很有趣 🙂
当正确使用时,正则表达式确实很快,但常常被误解并用于非正则的情况。
文章中提到了一个关于如何判断字符串是否包含数字的问题。文章中给出了几种不同的方法来解决这个问题,并进行了性能测试。
首先,文章给出了一个使用集合交集的方法来判断字符串是否包含数字的函数contains_digit_set_intersection
,该方法使用了digits.intersection(s)
来判断集合digits
和字符串s
的交集,如果交集不为空,则返回True,否则返回False。
接下来,文章还给出了其他几种方法来解决这个问题。其中contains_digit_iter_set
和contains_digit_iter_str
是使用迭代的方法来判断字符串中的每个字符是否在数字集合中,如果存在则返回True,否则返回False。而contains_digit_re
则是使用正则表达式\d
来匹配字符串中的数字,如果匹配成功则返回True,否则返回False。
文章还给出了对这几种方法进行性能测试的结果。测试结果显示,不同的方法在不同的计算机上的性能表现有所差异。其中contains_digit_set_intersection
方法在某台计算机上稍微快一些,而在另一台计算机上稍微慢一些。其他几种方法的性能表现也有所不同。
最后,文章指出了contains_digit_iter_set
方法的一个问题,并建议将其改为for d in digits: if d in s: return True
。此外,文章还提到了一些改进的方法,如定义digits
在函数外部,使用string.digits
或s.isdigit()
来代替string in digits
。
文章中主要介绍了几种不同的方法来判断字符串是否包含数字,并对这些方法进行了性能测试。同时,文章也提出了一些改进的建议来优化这些方法。
有没有一种更好的方法来判断字符串中是否包含数字?
这是一种情况,可以使用正则表达式来解决:
_digits = re.compile('\d') def contains_digits(d): return bool(_digits.search(d))
你也可以使用`any`方法和`.isdigit()`来判断,像's answer中描述的那样,但是这种方法比简单的正则表达式要慢:
import timeit timeit.timeit("contains_digits('0798237 sh 523-123-asdjlh')", 'from __main__ import contains_digits') 0.77181887626647949 timeit.timeit("contains_digits_any('0798237 sh 523-123-asdjlh')", 'from __main__ import contains_digits_any') 1.7796030044555664
使用`if`方法和正则表达式的效果是一样的:
timeit.timeit("contains_digits_if('0798237 sh 523-123-asdjlh')", 'from __main__ import contains_digits_if') 0.87261390686035156
但是如果数字出现在文本的后面,情况会变得更糟:
timeit.timeit("contains_digits('asdjlhtaheoahueoaea 11 thou')", 'from __main__ import contains_digits') 1.202538013458252 timeit.timeit("contains_digits_any('asdjlhtaheoahueoaea 11 thou')", 'from __main__ import contains_digits_any') 5.0348429679870605 timeit.timeit("contains_digits_if('asdjlhtaheoahueoaea 11 thou')", 'from __main__ import contains_digits_if') 3.707183837890625
为什么不直接使用`return bool(_digits.search(d))`?
因为我没有马上想到这个方法?:-)
在我的机器上,时间测试结果大致相同...(都是大约0.6)
我得到的结果是0.84秒和0.96秒(2.7.3)。但即使正则表达式快了好几倍,只有当它成为瓶颈时,我才会使用它。我更喜欢用Python编写代码。
在哪个版本的Python上?我的测试是在2.6上进行的,Mac OS 10.7。在2.7上结果更接近一些(0.95 vs 1.24),但是正则表达式仍然更高效一些。当数字出现在字符串的后面时,计时变化更大。
Python 2.7.3 OS: Linux 3.2.0-23(Ubuntu 12.04)- 不过,令人担忧的是,2.6使用`any`时速度几乎是2.7的一半!
我猜测`isdigit()`的测试效率不高;它被调用的字符越多,性能越差。 Pieters:你是对的。`isdigit(d)`比只测试`d in "0123456789"`要慢得多。可能是因为`isdigit`也可以处理"123"之类的字符串,检查所有的字符是否都是数字。
嗨,我试图找到与上面相同的结果,需要检查一个字符串中是否包含数字,但使用上面的方法显示“global name '_digits' is not defined”。
看起来你忘了一行代码。