Compruebe si una cadena contiene un número

193

La mayoría de las preguntas que he encontrado están sesgadas por el hecho de que están buscando letras en sus números, mientras que estoy buscando números en lo que me gustaría que fuera una cadena sin número. Necesito ingresar una cadena y verificar si contiene algún número y si lo rechaza.

La función isdigit()solo regresa Truesi TODOS los caracteres son números. Solo quiero ver si el usuario ha ingresado un número para una oración como "I own 1 dog"o algo así.

¿Algunas ideas?

DonnellyOverflow
fuente

Respuestas:

291

Puedes usar anyfunction, con la str.isdigitfunción, así

>>> def hasNumbers(inputString):
...     return any(char.isdigit() for char in inputString)
... 
>>> hasNumbers("I own 1 dog")
True
>>> hasNumbers("I own no dog")
False

Alternativamente, puede usar una expresión regular, como esta

>>> import re
>>> def hasNumbers(inputString):
...     return bool(re.search(r'\d', inputString))
... 
>>> hasNumbers("I own 1 dog")
True
>>> hasNumbers("I own no dog")
False
thefourtheye
fuente
¿Qué pasa con los números negativos?
Rayo
@Ray Entonces, el RegEx puede extenderse asír'-?\d+'
cuarto de
15
¿La expresión regular original no detectaría los números negativos de todos modos?
confused00
1
@ confused00 No, \dsolo coincidirá con un solo dígito en el rango 0de 9.
thefourtheye
9
@thefourtheye: -1 sigue siendo un dígito. Es un guión, seguido del dígito '1'
user3183018
49

Puede usar una combinación de anyy str.isdigit:

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

La función volverá Truesi existe un dígito en la cadena, de lo contrario False.

Manifestación:

>>> king = 'I shall have 3 cakes'
>>> num_there(king)
True
>>> servant = 'I do not have any cakes'
>>> num_there(servant)
False
aIKid
fuente
No es necesario crear una lista temporal, puede utilizar una expresión generadora simplemente eliminando esos corchetes.
Matteo Italia
Ah sí, me acabo de dar cuenta de que anyacepta expresiones generadoras.
aIKid
30

utilizar

str.isalpha () 

Ref: https://docs.python.org/2/library/stdtypes.html#str.isalpha

Devuelve verdadero si todos los caracteres de la cadena son alfabéticos y hay al menos un carácter, de lo contrario, falso.

K246
fuente
8
Hay otros tipos de caracteres que no son alfabéticos y numéricos, por ejemplo, '_'.isalpha()es falso.
lvc
28

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

Deberías usar mejor la expresión regular. Es mucho mas rapido.

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
zyxue
fuente
f3 no devuelve nada
pyd
Eso significa que no hay coincidencia, regresaNone
zyxue
RE_D = re.compile ('\ d') def has_digits (string): res = RE_D.search (string) return res no es None
Raul
8

Puede aplicar la función isdigit () en cada carácter de la cadena. O podrías usar expresiones regulares.

También encontré ¿Cómo encuentro un número en una cadena en Python? con formas muy adecuadas para devolver números. La solución a continuación es de la respuesta en esa pregunta.

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

Alternativamente:

number = filter(str.isdigit, yourString)

Para obtener más información, consulte el documento regex: http://docs.python.org/2/library/re.html

Editar: Esto devuelve los números reales, no un valor booleano, por lo que las respuestas anteriores son más correctas para su caso

El primer método devolverá el primer dígito y los siguientes dígitos consecutivos. Por lo tanto, 1.56 se devolverá como 1. 10.000 se devolverá como 10. 0207-100-1000 se devolverá como 0207.

El segundo método no funciona.

Para extraer todos los dígitos, puntos y comas, y no perder dígitos no consecutivos, use:

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

Puede usar el método NLTK para ello.

Esto encontrará tanto '1' como 'Uno' en el texto:

import nltk 

def existence_of_numeric_data(text):
    text=nltk.word_tokenize(text)
    pos = nltk.pos_tag(text)
    count = 0
    for i in range(len(pos)):
        word , pos_tag = pos[i]
        if pos_tag == 'CD':
            return True
    return False

existence_of_numeric_data('We are going out. Just five you and me.')
Mahendra S. Chouhan
fuente
2

Puede lograr esto de la siguiente manera:

if a_string.isdigit(): do_this() else: do_that()

https://docs.python.org/2/library/stdtypes.html#str.isdigit

Usar .isdigit()también significa no tener que recurrir al manejo de excepciones (try / except) en los casos en que necesite usar la comprensión de la lista (try / except no es posible dentro de una comprensión de la lista).

olisteadman
fuente
2

Puede usar el rango con conteo para verificar cuántas veces aparece un número en la cadena al compararlo con el rango:

def count_digit(a):
    sum = 0
    for i in range(10):
        sum += a.count(str(i))
    return sum

ans = count_digit("apple3rh5")
print(ans)

#This print 2
pedmindset
fuente
2

Me sorprende que nadie haya mencionado esta combinación de anyy map:

def contains_digit(s):
    isdigit = str.isdigit
    return any(map(isdigit,s))

en python 3 es probablemente el más rápido allí (excepto tal vez para expresiones regulares) es porque no contiene ningún bucle (y aliasing la función evita buscarlo en str ).

No use eso en python 2 como mapdevuelve a list, que rompe anyel cortocircuito

Jean-François Fabre
fuente
2

¿Qué hay de este?

import string

def containsNumber(line):
    res = False
    try:
        for val in line.split():
            if (float(val.strip(string.punctuation))):
                res = True
                break
    except ValueError:
        pass
    return res

containsNumber('234.12 a22') # returns True
containsNumber('234.12L a22') # returns False
containsNumber('234.12, a22') # returns True
aga
fuente
1
Por favor, no solo arroje su código fuente aquí. Sé amable y trata de dar una buena descripción a tu respuesta, para que a otros les guste y la voten. Ver: ¿Cómo escribo una buena respuesta?
sɐunıɔ ןɐ qɐp
2

Haré que la respuesta @zyxue sea un poco más explícita:

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

cuál es la solución con el punto de referencia más rápido de las soluciones que @zyxue propuso en la respuesta.

Raul
fuente
1

La forma más simple de resolver es como

s = '1dfss3sw235fsf7s'
count = 0
temp = list(s)
for item in temp:
    if(item.isdigit()):
        count = count + 1
    else:
        pass
print count
Tormenta de nieve
fuente
1
¡Bienvenido a Stack Overflow! Por favor, no solo arroje su código fuente aquí. Sé amable y trata de dar una buena descripción a tu respuesta, para que a otros les guste y la voten. Ver: ¿Cómo escribo una buena respuesta?
sɐunıɔ ןɐ qɐp
1
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)

Este código genera una secuencia con tamaño n que al menos contiene mayúsculas, minúsculas y un dígito. Al usar el ciclo while, hemos garantizado este evento.

Mehran Attar
fuente
Agregue una explicación a su respuesta
Mastisa
1

anyy ordse puede combinar para cumplir el propósito que se muestra a continuación.

>>> def hasDigits(s):
...     return any( 48 <= ord(char) <= 57 for char in s)
...
>>> hasDigits('as1')
True
>>> hasDigits('as')
False
>>> hasDigits('as9')
True
>>> hasDigits('as_')
False
>>> hasDigits('1as')
True
>>>

Un par de puntos sobre esta implementación.

  1. any es mejor porque funciona como expresión de cortocircuito en lenguaje C y devolverá el resultado tan pronto como se pueda determinar, es decir, en el caso de la cadena 'a1bbbbbbc' 'b' y 'c' ni siquiera se compararán.

  2. ordes mejor porque brinda más flexibilidad como números de cheques solo entre '0' y '5' o cualquier otro rango. Por ejemplo, si escribiera un validador para la representación hexadecimal de números, desearía que la cadena tuviera alfabetos en el rango 'A' a 'F' solamente.

ViFI
fuente
1
alp_num = [x for x in string.split() if x.isalnum() and re.search(r'\d',x) and 
re.search(r'[a-z]',x)]

print(alp_num)

Esto devuelve toda la cadena que tiene tanto alfabetos como números. isalpha () devuelve la cadena con todos los dígitos o todos los caracteres.

Sai ram
fuente
0

Probablemente este no sea el mejor enfoque en Python, pero como Haskeller, este enfoque lambda / mapa tenía mucho sentido para mí y es muy corto:

anydigit = lambda x: any(map(str.isdigit, x))

No necesita ser nombrado, por supuesto. Nombrado podría usarse como anydigit("abc123"), ¡lo que se siente como lo que estaba buscando!

Oscar South
fuente