Comprobar si la cadena contiene un número en Python

Introducción

Ya sea que esté creando un script de verificación para la entrada del usuario, un formulario de inicio de sesión que solicite a los usuarios que incluyan un carácter en una contraseña, verificar si una cadena contiene un carácter no es una operación poco común.

En este tutorial, veremos las muchas formas en que puede verificar si una cadena contiene un dígito/número en Python, incluido un punto de referencia para el enfoque más eficiente al final.

Comprobar si la cadena contiene un número en Python

Hay varias formas de comprobar si un personaje es un númeroord(), isnumeric(), isdigit()), que puede acoplar con un bucle for, para verificar al menos un solo resultado positivo. De manera alternativa, puede usar expresiones regulares como comparadores de patrones generales, que son flexibles, potentes y están diseñados para aplicarse a grandes corpus de texto. Finalmente, siempre puedes map() cada personaje recibe una declaración condicional y regresa True is any() de ellos dan como resultado True.

La elección entre estos debe tener en cuenta la eficiencia de los métodos, la verbosidad y el estilo de codificación, así como las tareas previas o posteriores asociadas con la operación.

Comprobar si la cadena contiene un número con ord()

El ord() La función toma un carácter y devuelve su ASCII valor:

print(ord('0')) 
print(ord('9')) 

El valor ASCII de 0 es 48, y el valor ASCII de 9 es 57. Cualquier número entre estos, será por extensión, tener un valor ASCII entre 48 y 57. Ahora, para verificar si la cadena tiene algún número, recorreremos toda la cadena de entrada y verificaremos el valor ASCII de cada carácter, si el valor ASCII es mayor que 47 y menor que 58, significa que es un número, y regresaremos True:

input_string = "My name is Satyam & I am 22 yrs old"
flag = False
for ch in input_string:
    ascii_code = ord(ch)
    if 47 < ascii_code < 58:
        flag = True
        break
if flag:
    print("Yes, the string contains a number.")
else:
    print("No, the string does not contain a number.")

Esto resulta en:

Yes, the string contains a number.

Comprobar si la cadena contiene un número con isnumeric()

El isnumeric() la función vuelve True si la cadena de entrada contiene solo números; de lo contrario, devuelve False:

str1 = "918"
print("String is whole numeric?", str1.isnumeric())
str2 = "The meaning of the universe is 42"
print("String is whole numeric?", str2.isnumeric())

Esto resulta en:

String is whole numeric? True 
String is whole numeric? False

Nota: El isnumeric() función no se comportará como se puede esperar para números negativos o flotantes. Si pasamos una cadena con solo números negativos o flotantes, devolverá False, Debido a que el - y . los caracteres asociados con números negativos y flotantes no son números.

str1 = "-918"
print("String is whole numeric?", str1.isnumeric()) 

str2 = "91.8"
print("String is whole numeric?", str2.isnumeric()) 

Sin embargo, dado que los caracteres son solo cadenas de longitud 1 en Python, puede iterar a través de los caracteres y usar isnumeric() para comprobar si son un número:

input_string = "My name is Satyam & I am 22 yrs old"
flag = False
for ch in input_string:
    if ch.isnumeric():
        flag = True
        break
if flag:
    print("Yes, the string contains a number.")
else:
    print("No, the string does not contain a number.")

Comprobar si la cadena contiene un número con isdigit()

El isdigit() La función comprueba si todos los caracteres de una cadena son dígitos. Si es así, vuelve True, y si no, vuelve False. Nuevamente, dado que los caracteres son solo cadenas de longitud 1 en Python, este método se puede usar en un ciclo para cada carácter:

input_string = "My name is Satyam & I am 22 yrs old"
flag = False
for ch in input_string:
    if ch.isdigit():
        flag = True
        break
if flag:
    print("Yes, the string contains a number.")
else:
    print("No, the string does not contain a number.")

Nota: El isdigit() El método sólo se comporta de la misma manera que isnumeric(), y si le pasa una cadena que contiene un flotante o un número negativo, False se devuelve debido a que los caracteres especiales no son números. Sin embargo, a nivel de personaje, si tan largo como uno True El valor es suficiente para determinar si la cadena contiene un número; es aplicable.

¿Diferencia entre isnumeric () e isdigit ()?

Entonces, ¿cuál es la diferencia entre isnumeric() y isdigit()? Mientras estamos en eso, ¿qué pasa con isdecimal()?

  • isnumeric() comprueba si algún carácter es un representación unicode creando valor numérico (que incluye representaciones numéricas romanas, superíndices, subíndices y fracciones)
  • isdigit() comprueba si algún carácter es un dígito unicode (que no incluye representaciones numéricas romanas, pero sí super/subíndices y fracciones)
  • isdecimal() comprueba si algún carácter es un dígito decimal (que volvería False por cualquier cosa que no sea 0..9 en base 10)

isnumeric() es el método más amplio, mientras que isdecimal() es el más estrecho entre los tres.

Compruebe si la cadena contiene un número con map() y any()

El map() La función ejecuta la función proporcionada para cada elemento del iterable pasado en la función de mapa. Cada elemento de un iterable se pasa a la función como un parámetro:

map(function, iterable)

El function se ejecuta para cada elemento del iterable. Esto permite una lógica muy flexible y poderosa, limitada únicamente por la extensión de la function usted llama a la entrada! El método devuelve un map ejemplo, que se puede convertir fácilmente en otras colecciones, como una lista o un conjunto.

Podemos escribir una función que devuelva un booleano que represente si un carácter es un número, y el map() call dará como resultado una lista de valores booleanos.

El any() devoluciones True si algún elemento del iterable pasado es True, de lo contrario, vuelve False.

Al unir estos dos, podemos crear un script corto de alto nivel y abstraer el bucle for:

def func(ch):
    return ch.isdigit() 

input_string = "My name is Satyam & I am 22 yrs old"
contains_number = any(list(map(func, input_string)))
print("Is there a number present?", contains_number)

Esto resulta en:

Is there a number present? True

Si su función es de una sola línea, no hay necesidad de extraerla como una función con nombre. Puedes escribir un anonimo función lambda en cambio por el bien de la brevedad:

Consulte nuestra guía práctica y práctica para aprender Git, con las mejores prácticas, los estándares aceptados por la industria y la hoja de trucos incluida. Deja de buscar en Google los comandos de Git y, de hecho, aprenden ella!

input_string = "My name is Satyam & I am 22 yrs old"
contains_number = any(list(map(lambda ch: ch.isdigit(), input_string)))
print("Is there any number present?", contains_number)

Esto también resulta en:

Is there any number present? True

Comprobar si la cadena contiene un número en Python con expresiones regulares

Las expresiones regulares son patrones de búsqueda diseñado para compararse con el texto de entrada. Son flexibles y, dada su naturaleza, puede escribir un número arbitrario de expresiones para buscar el mismo patrón, así como cubrir cualquier patrón manejable que se le ocurra.

Python re El módulo se utiliza para escribir, compilar y comparar texto con expresiones regulares. Expone varios métodos, tales como match() que coincide con si una cadena comienza con un patrón, search() que encuentra la primera aparición de posiblemente muchas coincidencias en una cadena, y findall() que verifica todas las ocurrencias.

Nota: Los tres métodos aceptan un pattern y search argumento y ejecute una búsqueda del pattern existentes search cadena.

El patrón que identifica a un dígito is "d+":

import re
input_string = "My name is Satyam & I am 22 yrs old"
match = re.search(r"d+", input_string)
if match:
    print("Is there any number present?", "Yes")
else:
    print("Is there any number present?", "No")

El search() el método devuelve un re.Match objeto, que contiene la coincidencia encontrada y los índices inicial y final:


El objeto se puede evaluar a un valor booleano en función de si es un re.Match objeto o None. Esto resulta en:

Is there any number present? Yes

A diferencia de la search() método, el findall() El método devuelve todas las ocurrencias del patrón en lugar de solo la primera:

import re
input_string = "My name is Satyam & I am 22 yrs old"
match = re.findall(r"d+", input_string)
if match:
    print("Is there any number present?", "Yes")
else:
    print("Is there any number present?", "No")

Esto resulta en:

Is there any number present? Yes

Evaluación comparativa

¿Qué pasa con el rendimiento? Si extrae la lógica y recorta las partes innecesarias, limitando los métodos a devolver solo el resultado, puede compararlos fácilmente entre sí en la misma entrada:

%timeit ord_check()
%timeit isnumeric_check()
%timeit is_digit_check()
%timeit lambda_check()
%timeit regex_check()

Esto resulta en:

2.18 µs ± 51.5 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
2.04 µs ± 639 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
1.88 µs ± 448 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
5.07 µs ± 915 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
1.47 µs ± 3.41 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)

Generalmente, los enfoques de bucle for se ejecutan aproximadamente al mismo tiempo, con poca sobrecarga de los métodos específicos. lambda con any() es de facto el más lento (muchas operaciones redundantes, debido a convertir una lista en una lista y luego reducirla), mientras que las expresiones regulares tuvieron el tiempo de ejecución más rápido con la variación más baja a su alrededor (son constantemente rápidos).

Sin embargo, en textos de entrada más largos, se enfatizan las complejidades de tiempo en cada uno de los diferentes enfoques, especialmente dependiendo de la cantidad de dígitos coincidentes (si los dígitos son comunes o no):

import random
import string

input_string_random = ''.join(random.choices(string.ascii_uppercase + string.digits, k=1000))
print(input_string_random) 

input_string_with_single_digit = ''.join(random.choices(string.ascii_uppercase, k=1000)) + '1'
print(input_string_with_single_digit) 

La primera cadena genera una secuencia aleatoria con aproximadamente la misma cantidad de dígitos y caracteres, mientras que la última es una cadena de solo caracteres con un solo dígito al final (peor complejidad de tiempo):

%timeit ord_check(input_string_random)
504 ns ± 22.6 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
%timeit ord_check(input_string_with_single_digit)
76.2 µs ± 1.36 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
%timeit isnumeric_check(input_string_random)
756 ns ± 170 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
%timeit isnumeric_check(input_string_with_single_digit)
76.2 µs ± 8.43 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
%timeit is_digit_check(input_string_random)
549 ns ± 102 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
%timeit is_digit_check(input_string_with_single_digit)
65 µs ± 20.6 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
%timeit lambda_check(input_string_random)
114 µs ± 8.77 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
%timeit lambda_check(input_string_with_single_digit)
119 µs ± 6.23 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
%timeit regex_check(input_string_random)
996 ns ± 19.8 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
%timeit regex_check(input_string_with_single_digit)
22.2 µs ± 1.77 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)

Con un bajo número de aciertos, las expresiones regulares son las de mayor rendimiento. Con muchos aciertos, el enfoque de la función lambda es el de mayor rendimiento y conserva su complejidad temporal independientemente de si la entrada tiene muchos hits o uno. La principal desventaja (el cálculo redundante cuando la tasa de aciertos es baja) se convierte en su principal fortaleza, ya que la redundancia hace que la entrada sea robusta.

Conclusión

En este tutorial, echamos un vistazo a varias formas de verificar si una cadena en Python contiene al menos un carácter. Hemos echado un vistazo a la ord(), isnumeric(), isdigit() y isdecimal() función, así como cómo abstraer esta lógica con una llamada de función lambda usando map() y any(). Luego, exploramos las expresiones regulares y comparamos los enfoques con diferentes aportes.

Sello de tiempo:

Mas de Abuso de pila