Sjekk om strengen inneholder et tall i Python

Introduksjon

Enten du bygger et bekreftelsesskript for brukerinndata, er et påloggingsskjema som ber brukere om å inkludere et tegn i et passord – det å sjekke om en streng inneholder et tegn ikke en uvanlig operasjon.

I denne opplæringen – vi tar en titt på de mange måtene du kan sjekke om en streng inneholder et siffer/tall i Python, inkludert en målestokk for den mest effektive tilnærmingen til slutt.

Sjekk om strengen inneholder tall i Python

Det er flere måter å sjekke om en karakter er et tall (ord(), isnumeric(), isdigit()), som du kan koble til en for-løkke, for å se etter minst ett enkelt positivt treff. Alternativt kan du bruke regulære uttrykk som generelle mønstermatchere, som er fleksible, kraftige og designet for å brukes på store tekstkorpuser. Endelig – du kan alltid map() hvert tegn gitt en betinget uttalelse, og returner True is any() av dem resulterer i True.

Valget mellom disse bør ta hensyn til effektiviteten til metodene, detaljerthet og kodestil, samt oppstrøms- eller nedstrømsoppgaver knyttet til operasjonen.

Sjekk om strengen inneholder tall med ord()

De ord() funksjonen tar et tegn og returnerer dens ASCII verdi:

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

ASCII-verdien til 0 er 48, og ASCII-verdien på 9 er 57. Et hvilket som helst tall mellom disse vil i forlengelsen, har en ASCII-verdi mellom 48 og 57. Nå for å sjekke om strengen har noe tall, vil vi krysse hele inndatastrengen og sjekke ASCII-verdien til hvert tegn, hvis ASCII-verdien er mer enn 47 og mindre enn 58, betyr det at det er et tall, og vi kommer tilbake 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.")

Dette resulterer i:

Yes, the string contains a number.

Sjekk om strengen inneholder tall med isnumeric()

De isnumeric() funksjonen returnerer True hvis inndatastrengen bare inneholder tall, ellers returnerer den 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())

Dette resulterer i:

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

OBS: De isnumeric() funksjonen vil ikke oppføre seg som du kanskje forventer negative eller flytende tall. Hvis vi passerer en streng med bare negative eller flytende tall, kommer den tilbake False, fordi - og . tegn assosiert med negative tall og flyter er faktisk ikke tall.

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

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

Men siden karakterer bare er strenger med lengde 1 i Python – kan du iterere gjennom karakterer og bruke isnumeric() for å sjekke om de er et tall:

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

Sjekk om strengen inneholder tall med isdigit()

De isdigit() funksjonen sjekker om alle tegnene i en streng er sifre. Hvis ja – kommer den tilbake True, og hvis ikke, kommer den tilbake False. Igjen, siden tegn bare er strenger med lengde 1 i Python - denne metoden kan brukes i en løkke for hvert tegn:

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

OBS: De isdigit() metoden bare oppfører seg på samme måte som isnumeric(), og hvis du sender en streng som inneholder en flottør eller et negativt tall til den, False returneres på grunn av at spesialtegnene ikke er tall. Men på karakternivå, om så lenge som en True verdi er nok til å avgjøre om strengen inneholder et tall – det er aktuelt.

Forskjellen mellom isnumeric() og isdigit()?

Så hva er forskjellen mellom isnumeric() og isdigit()? Mens vi er i gang – hva med isdecimal()?

  • isnumeric() sjekker om et tegn er en unicode-representasjon av en numerisk verdi (som inkluderer romerske numeriske representasjoner, hevet skrift, senket skrift og brøk)
  • isdigit() sjekker om et tegn er en unicode-siffer (som ikke inkluderer romerske numeriske representasjoner, men inkluderer super/subscripts og brøker)
  • isdecimal() sjekker om noen tegn er en desimaltall (som ville komme tilbake False for alt som ikke er det 0..9 i base 10)

isnumeric() er den mest brede metoden, mens isdecimal() er den smaleste mellom de tre.

Sjekk om strengen inneholder tall med map() og any()

De map() funksjonen utfører den angitte funksjonen for hvert element av iterablen som sendes i kartfunksjonen. Hvert element i en iterabel sendes til funksjonen som en parameter:

map(function, iterable)

De function utføres for hvert element i iterable. Dette åpner for svært fleksibel og kraftig logikk, bare begrenset av omfanget av function du kaller på innspillet! Metoden returnerer en map forekomst, som enkelt kan gjøres om til andre samlinger, for eksempel en liste eller et sett.

Vi kan skrive en funksjon som returnerer en boolsk verdi som representerer om et tegn er et tall, og map() call vil dermed resultere i en liste over boolske verdier.

De any() avkastning True hvis noe element i den bestått iterable er True, ellers kommer den tilbake False.

Ved å sette disse to sammen – vi kan lage et kort manus på høyt nivå og abstrahere for-løkken:

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)

Dette resulterer i:

Is there a number present? True

Hvis funksjonen din er en one-liner – er det ikke nødvendig å trekke den ut som en navngitt funksjon. Du kan skrive en anonym lambda-funksjon i stedet for korthets skyld:

Sjekk ut vår praktiske, praktiske guide for å lære Git, med beste praksis, bransjeaksepterte standarder og inkludert jukseark. Slutt å google Git-kommandoer og faktisk lære den!

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)

Dette resulterer også i:

Is there any number present? True

Sjekk om streng inneholder tall i Python med regulære uttrykk

Vanlige uttrykk er søkemønstre designet for å matches mot inndatatekst. De er fleksible og gitt sin natur – du kan skrive et vilkårlig antall uttrykk for det samme mønsteret å søke etter, i tillegg til å dekke ethvert trekkbart mønster du kan tenke deg.

Pythons re modulen brukes til å skrive, kompilere og matche tekst mot regulære uttrykk. Den avslører ulike metoder, som f.eks match() som samsvarer med om en streng begynner med et mønster, search() som finner den første forekomsten av muligens mange treff i en streng, og findall() som sjekker for alle hendelser.

OBS: Alle tre metodene godtar en pattern og search argument og søk etter pattern i search streng.

Mønsteret som identifiserer en sifret 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")

De search() metoden returnerer a re.Match objekt, som inneholder samsvaret funnet og start- og sluttindeksene:


Objektet kan evalueres til en boolsk verdi basert på om det er en re.Match objekt eller None. Dette resulterer i:

Is there any number present? Yes

I motsetning til search() metode, findall() metoden returnerer alle forekomster av mønsteret i stedet for bare den første:

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

Dette resulterer i:

Is there any number present? Yes

Benchmarking

Hva med forestillingen? Hvis du trekker ut logikken og trimmer de unødvendige delene, og begrenser metodene til kun å returnere resultatet, kan du enkelt måle dem mot hverandre på samme inngang:

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

Dette resulterer i:

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)

Generelt går for-loop-tilnærmingene inn omtrent samtidig, med lite overhead fra de spesifikke metodene. Lambda med any() er defacto den tregeste (mange overflødige operasjoner, på grunn av å konvertere en liste til en liste og deretter redusere den), mens Regular Expressions hadde den raskeste kjøretiden med den laveste variansen rundt seg (de er konsekvent raske).

På lengre inndatatekster blir imidlertid tidskompleksitetene på hver av de forskjellige tilnærmingene vektlagt, spesielt avhengig av antall samsvarende sifre (om sifre er vanlige eller ikke):

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) 

Den første strengen genererer en tilfeldig sekvens med omtrent like mange sifre og tegn, mens sistnevnte er en streng med kun tegn med et enkelt siffer til slutt (verste tidskompleksitet):

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

Med et lavt antall treff - Regular Expressions er de mest presterende. Med mange treff er lambdafunksjonstilnærmingen den mest effektive, og den beholder sin tidskompleksitet uavhengig av om inngangen har mange treff eller ett. Den største ulempen (reduntant beregning når trefffrekvensen er lav) blir omgjort til dens hovedstyrke ettersom redundans gjør den robust for input.

konklusjonen

I denne opplæringen tok vi en titt på flere måter å sjekke om en streng i Python inneholder minst ett tegn. Vi har tatt en titt på ord(), isnumeric(), isdigit() og isdecimal() funksjon, samt hvordan abstrahere denne logikken med et lambda-funksjonskall ved hjelp av map() og any(). Deretter utforsket vi regulære uttrykk og benchmerket tilnærmingene med varierende innspill.

Tidstempel:

Mer fra Stackabuse