检查一个字符串是否包含数字

325

大部分我找到的问题都是基于寻找数字中是否包含字母,而我想在一个没有数字的字符串中查找数字。

我需要输入一个字符串,并检查其是否包含任何数字,如果包含数字,则拒绝该字符串。

isdigit()函数只有当所有字符都是数字时才返回True。我只想知道用户是否输入了一个数字,比如像"我有1只狗"这样的句子。

有什么想法吗?

20个回答

481

您可以使用any函数,结合str.isdigit函数,像这样:

def has_numbers(inputString):
    return any(char.isdigit() for char in inputString)

has_numbers("I own 1 dog")
# True
has_numbers("I own no dog")
# False

或者您可以使用正则表达式,像这样

import re
def has_numbers(inputString):
    return bool(re.search(r'\d', inputString))

has_numbers("I own 1 dog")
# True
has_numbers("I own no dog")
# False

2
负数怎么办? - Ray
1
@Ray 然后正则表达式可以扩展为 r'-?\d+' - thefourtheye
23
原始正则表达式不是已经可以检测到负数了吗? - confused00
2
@confused00 不,\d 只会匹配范围在 09 之间的单个数字。 - thefourtheye
15
-1仍然是一个数字。它是一个横杠,后面跟着数字'1'。 - user3183018
显示剩余2条评论

79

您可以使用 anystr.isdigit 的组合:

def num_there(s):
    return any(i.isdigit() for i in s)

如果字符串中存在一个数字,该函数将返回True,否则返回False

演示:

>>> king = 'I shall have 3 cakes'
>>> num_there(king)
True
>>> servant = 'I do not have any cakes'
>>> num_there(servant)
False

1
不需要创建临时列表,你可以使用生成器表达式,只需删除那些方括号。 - Matteo Italia
啊,是的,我刚意识到 any 可以接受生成器表达式。 - aIKid

44

22
除了字母和数字外,还有其他类型的字符 - 例如,'_'.isalpha() 的结果为False。 - lvc
1
像'ç'和'ñ'这样的字符将无法识别。例如,字符'œ'出现在中古英语文本中。 - Eduardo Freitas
使用此函数时,空格字符也被视为非字母字符,这在全名中是常见的字符。 - Ibrahim.H
空格字符在使用此函数时也被视为非字母字符,这在姓名中是常见的情况。 - undefined

36

https://docs.python.org/2/library/re.html

你最好使用正则表达式,它的速度更快。

import re

def f1(string):
    return any(i.isdigit() for i in string)


def f2(string):
    return re.search('\d', string)


# if you compile the regex string first, it's even faster
RE_D = re.compile('\d')
def f3(string):
    return RE_D.search(string)

# Output from iPython
# In [18]: %timeit  f1('assdfgag123')
# 1000000 loops, best of 3: 1.18 µs per loop

# In [19]: %timeit  f2('assdfgag123')
# 1000000 loops, best of 3: 923 ns per loop

# In [20]: %timeit  f3('assdfgag123')
# 1000000 loops, best of 3: 384 ns per loop

f3 没有返回任何东西。 - Pyd
这意味着没有匹配,它会返回 None - zyxue
RE_D = re.compile('\d')def has_digits(string): res = RE_D.search(string) return res is not None - Raul
@Raul 如果匹配成功,f2f3 将返回 re.Match 对象,否则返回 None。要获取一个布尔值,只需将结果包装在 bool(re. ...) 中即可。 - cards

12
您可以对字符串中的每个字符应用函数isdigit()。或者您可以使用正则表达式。

我还发现如何在Python中查找字符串中的一个数字?,其中提供了非常适合返回数字的方法。下面的解决方案来自于该问题的答案。

number = re.search(r'\d+', yourString).group()

或者:

number = filter(str.isdigit, yourString)

要了解更多信息,请查看正则表达式文档:http://docs.python.org/2/library/re.html

编辑:这将返回实际数字,而不是布尔值,因此上面的答案更适合您的情况。

第一种方法将返回第一个数字和随后的连续数字。因此,1.56将被返回为1。 10,000将被返回为10。0207-100-1000将作为0207返回。

第二种方法不起作用。

要提取所有数字、句点和逗号,并且不丢失非连续数字,请使用:

re.sub('[^\d.,]' , '', yourString)

7

我会让 @zyxue 的回答更明确一些:

import re    

RE_D = re.compile('\d')

def has_digits(string):
    res = RE_D.search(string)
    return res is not None

has_digits('asdf1')
Out: True

has_digits('asdf')
Out: False

在@zyxue提出的解決方案中,哪個是具有最快基準測試的解決方案。


6
我很惊讶没有人提到anymap的组合:
def contains_digit(s):
    isdigit = str.isdigit
    return any(map(isdigit,s))

在Python 3中,除了正则表达式可能更快之外,这可能是最快的原因是它不包含循环(并且别名函数可以避免在str中查找)。
不要在Python 2中使用此方法,因为map返回一个list,这会破坏any的短路效果。

3

您还可以使用set.intersection函数,对于小字符串来说,它非常快速,比正则表达式更好。

def contains_number(string):
    return True if set(string).intersection('0123456789') else False

2
import string
import random
n = 10

p = ''

while (string.ascii_uppercase not in p) and (string.ascii_lowercase not in p) and (string.digits not in p):
    for _ in range(n):
        state = random.randint(0, 2)
        if state == 0:
            p = p + chr(random.randint(97, 122))
        elif state == 1:
            p = p + chr(random.randint(65, 90))
        else:
            p = p + str(random.randint(0, 9))
    break
print(p)

这段代码生成一个大小为n的序列,其中至少包含一个大写字母、一个小写字母和一个数字。通过使用while循环,我们已经保证了这一事件发生。


1
请在您的答案中添加解释。 - mastisa

2

此外,您还可以使用正则表达式的“findall”功能。它是一种更通用的解决方案,因为它可以对数字的长度进行更多的控制。在需要具有最小长度的数字的情况下,它可能非常有用。

s = '67389kjsdk' 
contains_digit = len(re.findall('\d+', s)) > 0

1
问题很明确,没有说明需要控制数字的长度。你在回答另一个问题。如果您有改进建议,请点赞或留言。 - BcK

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