Verificați dacă șirul conține un număr în Python

Introducere

Indiferent dacă construiți un script de verificare pentru introducerea utilizatorului, un formular de autentificare care solicită utilizatorilor să includă un caracter într-o parolă - verificarea dacă un șir conține un caracter nu este o operațiune neobișnuită.

În acest tutorial – vom arunca o privire asupra numeroaselor moduri în care puteți verifica dacă un șir conține o cifră/număr în Python, inclusiv un punct de referință pentru cea mai eficientă abordare în cele din urmă.

Verificați dacă șirul conține un număr în Python

Există mai multe moduri de a verifica dacă a caracter este un număr (ord(), isnumeric(), isdigit()), pe care o puteți cupla cu o buclă for, pentru a verifica dacă există cel puțin o singură lovitură pozitivă. Alternativ, puteți utiliza expresiile regulate ca potriviri de modele generale, care sunt flexibile, puternice și concepute pentru a fi aplicate unor corpusuri mari de text. În sfârșit – poți oricând map() fiecărui personaj i se ia o declarație condiționată și returnează True is any() dintre ele rezultă în True.

Alegerea dintre acestea ar trebui să ia în considerare eficiența metodelor, verbozitatea și stilul de codare, precum și sarcinile din amonte sau din aval asociate operației.

Verificați dacă șirul conține un număr cu ord()

ord() funcția ia un caracter și îi returnează ASCII valoare:

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

Valoarea ASCII a 0 este 48, iar valoarea ASCII de 9 este 57. Orice număr dintre acestea va, prin extensie, au o valoare ASCII între 48 și 57. Acum, pentru a verifica dacă șirul are vreun număr, vom parcurge întregul șir de intrare și vom verifica valoarea ASCII a fiecărui caracter, dacă valoarea ASCII este mai mare de 47 și mai mică de 58, înseamnă că este un număr și vom reveni 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.")

Rezultă:

Yes, the string contains a number.

Verificați dacă șirul conține un număr cu isnumeric()

isnumeric() funcția revine True dacă șirul de intrare conține doar numere, în caz contrar, revine 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())

Rezultă:

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

Notă: isnumeric() funcția nu se va comporta așa cum vă așteptați numere negative sau flotante. Dacă trecem un șir cu doar numere negative sau flotante, acesta va reveni False, pentru că - și . caracterele asociate cu numere negative și flotanți sunt într-adevăr, nu numere.

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

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

Cu toate acestea, din moment ce caracterele sunt doar șiruri de lungime 1 în Python - puteți itera prin caractere și utilizați isnumeric() pentru a verifica dacă sunt un număr:

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.")

Verificați dacă șirul conține un număr cu isdigit()

isdigit() funcția verifică dacă toate caracterele dintr-un șir sunt cifre. Dacă da – revine True, iar dacă nu, se întoarce False. Din nou, deoarece caracterele sunt doar șiruri de lungime 1 în Python - această metodă poate fi folosită într-o buclă pentru fiecare caracter:

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.")

Notă: isdigit() metoda se comportă doar în același mod ca isnumeric(), iar dacă îi treceți un șir care conține un număr flotant sau un număr negativ, False este returnat deoarece caracterele speciale nu sunt numere. La nivel de personaj, totuși, dacă este atât de lung cât unul True valoarea este suficientă pentru a determina dacă șirul conține un număr – este aplicabil.

Diferența dintre isnumeric() și isdigit()?

Deci, care este diferența între isnumeric() și isdigit()? În timp ce suntem la asta – ce zici isdecimal()?

  • isnumeric() verifică dacă vreun caracter este a reprezentare unicode a unui valoare numerica (care include reprezentări numerice romane, superscripte, indice și fracții)
  • isdigit() verifică dacă vreun caracter este a cifra unicode (care nu include reprezentări numerice romane, dar include super/indice și fracții)
  • isdecimal() verifică dacă vreun caracter este a cifră zecimală (care s-ar întoarce False pentru orice nu este 0..9 în baza 10)

isnumeric() este cea mai largă metodă, în timp ce isdecimal() este cea mai îngustă dintre cele trei.

Verificați dacă șirul conține un număr cu map() și orice()

map() funcția execută funcția furnizată pentru fiecare element al iterabilului trecut în funcția map. Fiecare element al unui iterabil este transmis funcției ca parametru:

map(function, iterable)

function este executat pentru fiecare element al iterable. Acest lucru permite o logică foarte flexibilă și puternică, limitată doar de extinderea function suni la intrare! Metoda returnează a map exemplu, care poate fi ușor transformat în alte colecții, cum ar fi o listă sau un set.

Putem scrie o funcție care returnează un boolean reprezentând dacă un caracter este un număr și map() apelul va avea ca rezultat o listă de valori booleene.

any() Returnează True dacă vreun element al iterabilului trecut este True, altfel, revine False.

Împreună aceste două - putem crea un script scurt și de nivel înalt și putem abstra bucla-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)

Rezultă:

Is there a number present? True

Dacă funcția dvs. este o singură linie - nu este nevoie să o extrageți ca funcție numită. Puteți scrie un anonim funcția lambda în schimb, de dragul conciziei:

Consultați ghidul nostru practic și practic pentru a învăța Git, cu cele mai bune practici, standarde acceptate de industrie și fisa de cheat incluse. Opriți căutarea pe Google a comenzilor Git și de fapt învăţa aceasta!

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)

Acest lucru are ca rezultat și:

Is there any number present? True

Verificați dacă șirul conține un număr în Python cu expresii regulate

Expresiile regulate sunt modele de căutare conceput pentru a fi corelat cu textul introdus. Sunt flexibili și având în vedere natura lor – puteți scrie un număr arbitrar de expresii pentru același model de căutat, precum și acoperi orice model tractibil la care vă puteți gândi.

Python's re modulul este folosit pentru a scrie, compila și potrivi text cu expresii regulate. Expune diferite metode, cum ar fi match() care se potrivește dacă un șir începe cu un model, search() care găsește prima apariție a posibilelor multe potriviri într-un șir și findall() care verifică toate aparițiile.

Notă: Toate cele trei metode acceptă a pattern și search argument și rulați o căutare pentru pattern în search șir.

Modelul care identifică a cifră 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")

search() metoda returnează a re.Match obiect, care conține potrivirea găsită și indicii de început și de sfârșit:


Obiectul poate fi evaluat la o valoare booleană în funcție de faptul dacă este a re.Match obiect sau None. Aceasta are ca rezultat:

Is there any number present? Yes

Spre deosebire de search() Metoda, findall() metoda returnează toate aparițiile modelului în loc de doar prima:

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")

Rezultă:

Is there any number present? Yes

Benchmarking

Dar performanța? Dacă extrageți logica și tăiați părțile inutile, limitând metodele doar la returnarea rezultatului, le puteți compara cu ușurință una față de alta pe aceeași intrare:

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

Rezultă:

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)

În general, abordările for-loop rulează aproximativ în același timp, cu puțină suprasarcină de la metodele specifice. Lambda cu any() este de facto cel mai lent (multe operațiuni redundante, datorită conversiei unei liste într-o listă și apoi reducerii acesteia), în timp ce expresiile regulate au avut cel mai rapid timp de rulare cu cea mai mică variație în jurul acesteia (sunt în mod constant rapide).

Cu toate acestea, la textele de intrare mai lungi, complexitățile de timp pentru fiecare dintre abordările diferite sunt accentuate, în special în funcție de numărul de cifre potrivite (indiferent dacă cifrele sunt comune sau nu):

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) 

Primul șir generează o secvență aleatorie cu aproximativ un număr egal de cifre și caractere, în timp ce cel din urmă este un șir de caractere cu o singură cifră la sfârșit (cea mai proastă complexitate):

%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)

Cu un număr redus de accesări – expresiile regulate sunt cele mai performante. Cu multe accesări, abordarea funcției lambda este cea mai performantă și asta își păstrează complexitatea timpului indiferent dacă intrarea are mai multe accesări sau una. Principalul dezavantaj (calcul reduntant atunci când rata de lovituri este scăzută) se transformă în puterea sa principală, deoarece redundanța îl face robust la intrare.

Concluzie

În acest tutorial, am analizat mai multe moduri de a verifica dacă un șir în Python conține cel puțin un caracter. Ne-am uitat la ord(), isnumeric(), isdigit() și isdecimal() funcția, precum și cum să abstractizați această logică cu ajutorul unui apel de funcție lambda map() și any(). Apoi, am explorat expresiile regulate și am evaluat abordările cu diferite inputuri.

Timestamp-ul:

Mai mult de la Stackabuse