Kontrollera om strängen innehåller ett nummer i Python

Beskrivning

Oavsett om du bygger ett verifieringsskript för användarinmatning, ett inloggningsformulär som ber användare att inkludera ett tecken i ett lösenord – att kontrollera om en sträng innehåller ett tecken är inte en ovanlig operation.

I den här handledningen – vi ska ta en titt på de många sätt du kan kontrollera om en sträng innehåller en siffra/nummer i Python, inklusive ett riktmärke för den mest effektiva metoden i slutändan.

Kontrollera om strängen innehåller nummer i Python

Det finns flera sätt att kontrollera om en karaktär är ett nummer (ord(), isnumeric(), isdigit()), som du kan koppla ihop med en for-loop, för att kontrollera om det finns minst en enda positiv träff. Alternativt kan du använda Regular Expressions som allmänna mönstermatchare, som är flexibla, kraftfulla och designade för att appliceras på stora textkroppar. Äntligen – du kan alltid map() varje tecken ges ett villkorligt uttalande, och returnera True is any() av dem resulterar i True.

Att välja mellan dessa bör ta hänsyn till metodernas effektivitet, utförlighet och kodningsstil, såväl som uppströms- eller nedströmsuppgifter i samband med operationen.

Kontrollera om strängen innehåller nummer med ord()

Smakämnen ord() funktion tar ett tecken och returnerar dess ASCII värde:

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

ASCII-värdet på 0 är 48 och ASCII-värdet på 9 är 57. Varje nummer mellan dessa kommer i förlängningen, har ett ASCII-värde mellan 48 och 57. För att nu kontrollera om strängen har något nummer, kommer vi att gå igenom hela inmatningssträngen och kontrollera ASCII-värdet för varje tecken, om ASCII-värdet är mer än 47 och mindre än 58 betyder det att det är ett nummer, och vi kommer tillbaka 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.")

Detta resulterar i:

Yes, the string contains a number.

Kontrollera om strängen innehåller nummer med isnumeric()

Smakämnen isnumeric() funktionen återgår True om inmatningssträngen bara innehåller siffror, annars returnerar 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())

Detta resulterar i:

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

Notera: Smakämnen isnumeric() funktion kommer inte att fungera som du kan förvänta dig negativa eller flytande tal. Om vi ​​skickar en sträng med enbart negativa eller flytande tal, kommer den tillbaka False, eftersom - och . tecken associerade med negativa tal och flytande tal är verkligen inte siffror.

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

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

Men eftersom tecken bara är strängar av längd 1 i Python - kan du iterera genom tecken och använda isnumeric() för att kontrollera om de är ett nummer:

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

Kontrollera om strängen innehåller nummer med isdigit()

Smakämnen isdigit() funktionen kontrollerar om alla tecken i en sträng är siffror. Om ja – den kommer tillbaka True, och om inte kommer den tillbaka False. Återigen, eftersom tecken bara är strängar med längd 1 i Python – den här metoden kan användas i en loop för varje tecken:

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

Notera: Smakämnen isdigit() Metoden beter sig bara på samma sätt som isnumeric(), och om du skickar en sträng som innehåller ett flytande tal eller ett negativt tal till den, False returneras på grund av att specialtecknen inte är siffror. På karaktärsnivå, dock om så lång som en True värdet är tillräckligt för att avgöra om strängen innehåller ett nummer – det är tillämpligt.

Skillnaden mellan isnumeric() och isdigit()?

Så vad är skillnaden mellan isnumeric() och isdigit()? Medan vi håller på – vad sägs om isdecimal()?

  • isnumeric() kontrollerar om något tecken är en unicode-representation av en numeriskt värde (som inkluderar romerska numeriska representationer, upphöjda, nedsänkta och bråk)
  • isdigit() kontrollerar om något tecken är en unicode-siffra (som inte inkluderar romerska numeriska representationer, men inkluderar super/nedtecknade och bråk)
  • isdecimal() kontrollerar om några tecken är en decimalsiffran (som skulle komma tillbaka False för allt som inte är det 0..9 i bas 10)

isnumeric() är den mest breda metoden, medan isdecimal() är den smalaste av de tre.

Kontrollera om strängen innehåller nummer med map() och any()

Smakämnen map() funktionen exekverar den tillhandahållna funktionen för varje element i iterabeln som skickas i kartfunktionen. Varje element i en iterabel skickas till funktionen som en parameter:

map(function, iterable)

Smakämnen function exekveras för varje objekt i iterable. Detta möjliggör en mycket flexibel och kraftfull logik, endast begränsad av omfattningen av function du kallar på ingången! Metoden returnerar en map instans, som enkelt kan omvandlas till andra samlingar såsom en lista eller uppsättning.

Vi kan skriva en funktion som returnerar ett booleskt värde som representerar om ett tecken är ett tal, och map() anrop kommer alltså att resultera i en lista med booleska värden.

Smakämnen any() återgår True om något element i den godkända iterable är True, annars kommer den tillbaka False.

Genom att sammanfoga dessa två kan vi skapa ett kort manus på hög nivå och abstrahera for-loopen:

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)

Detta resulterar i:

Is there a number present? True

Om din funktion är en one-liner – det finns ingen anledning att extrahera den som en namngiven funktion. Du kan skriva en anonym lambda-funktion istället för korthetens skull:

Kolla in vår praktiska, praktiska guide för att lära dig Git, med bästa praxis, branschaccepterade standarder och medföljande fuskblad. Sluta googla Git-kommandon och faktiskt lära Det!

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)

Detta resulterar också i:

Is there any number present? True

Kontrollera om strängen innehåller nummer i Python med reguljära uttryck

Reguljära uttryck är sökmönster utformad för att matchas mot inmatad text. De är flexibla och med tanke på sin natur – du kan skriva ett godtyckligt antal uttryck för samma mönster att söka efter, samt täcka alla tänkbara mönster du kan tänka dig.

Pythons re modulen används för att skriva, kompilera och matcha text mot reguljära uttryck. Den exponerar olika metoder, som t.ex match() som matchar om en sträng börjar med ett mönster, search() som hittar den första förekomsten av möjligen många matchningar i en sträng, och findall() som kontrollerar alla händelser.

Notera: Alla tre metoder accepterar en pattern och search argument och kör en sökning efter pattern i search sträng.

Mönstret som identifierar a siffra 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")

Smakämnen search() metoden returnerar a re.Match objekt, som innehåller den hittade matchningen och start- och slutindex:


Objektet kan utvärderas till ett booleskt värde baserat på om det är en re.Match objekt eller None. Detta resulterar i:

Is there any number present? Yes

Till skillnad från search() metoden, findall() metod returnerar alla förekomster av mönstret istället för bara den första:

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

Detta resulterar i:

Is there any number present? Yes

Benchmarking

Hur är det med prestationen? Om du extraherar logiken och trimmar de onödiga delarna, begränsar metoderna till att endast returnera resultatet, kan du enkelt jämföra dem mot varandra på samma ingång:

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

Detta resulterar 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)

Generellt körs for-loop-tillvägagångssätten ungefär samtidigt, med lite overhead från de specifika metoderna. Lambda med any() är defacto den långsammaste (många reduntanta operationer, på grund av att konvertera en lista till en lista och sedan minska den), medan Regular Expressions hade den snabbaste körtiden med den lägsta variansen runt den (de är konsekvent snabba).

Men på längre inmatningstexter betonas tidskomplexiteten för var och en av de olika metoderna, särskilt beroende på antalet matchade siffror (om siffror är vanliga eller inte):

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örsta strängen genererar en slumpmässig sekvens med ungefär lika många siffror och tecken, medan den senare är en sträng med endast tecken med en enda siffra i slutet (sämsta tidskomplexitet):

%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 ett lågt antal träffar – Regular Expressions är de mest presterande. Med många träffar är lambdafunktionsmetoden den mest presterande, och den behåller sin tidskomplexitet oavsett om ingången har många träffar eller en. Den största nackdelen (reduntant beräkning när träfffrekvensen är låg) förvandlas till dess främsta styrka eftersom redundans gör den robust för inmatning.

Slutsats

I den här handledningen tittade vi på flera sätt att kontrollera om en sträng i Python innehåller minst ett tecken. Vi har tagit en titt på ord(), isnumeric(), isdigit() och isdecimal() funktion, samt hur man abstraherar denna logik med ett lambda-funktionsanrop med hjälp av map() och any(). Sedan utforskade vi reguljära uttryck och jämförde tillvägagångssätten med olika input.

Tidsstämpel:

Mer från Stackabuse