Tarkista Pythonissa, sisältääkö merkkijono numeron

esittely

Olitpa rakentamassa varmistusskriptiä käyttäjän syöttämistä varten, kirjautumislomake, joka pyytää käyttäjiä lisäämään merkin salasanaan – sen tarkistaminen, sisältääkö merkkijono merkin, ei ole harvinainen toimenpide.

Tässä opetusohjelmassa – tarkastelemme monia tapoja, joilla voit tarkistaa, sisältääkö merkkijono numeron/numeron Pythonissa, mukaan lukien vertailukohta tehokkaimmalle lähestymistavalle.

Tarkista Pythonissa, sisältääkö merkkijono numeron

On useita tapoja tarkistaa, onko a merkki on numero (ord(), isnumeric(), isdigit()), jonka voit yhdistää for-silmukalla tarkistaaksesi ainakin yhden positiivisen osuman. Vaihtoehtoisesti voit käyttää säännöllisiä lausekkeita yleisinä kuviovastaavina, jotka ovat joustavia, tehokkaita ja suunniteltu käytettäväksi suurissa tekstikappaleissa. Lopuksi – voit aina map() jokaiselle merkille annetaan ehdollinen lause, ja paluu True is any() niistä johtaa True.

Näiden välillä valittaessa tulee ottaa huomioon menetelmien tehokkuus, sananmukaisuus ja koodaustyyli sekä toimintaan liittyvät ylä- tai loppupään tehtävät.

Tarkista, sisältääkö merkkijono numeron komennolla ord()

- ord() funktio ottaa merkin ja palauttaa sen ASCII arvo:

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

ASCII-arvo 0 on 48 ja ASCII-arvo 9 on 57. Mikä tahansa luku näiden välissä, laajentaa ASCII-arvo on välillä 48-57. Nyt tarkistaaksemme onko merkkijonossa jokin numero, käymme läpi koko syötemerkkijonon ja tarkistamme jokaisen merkin ASCII-arvon. Jos ASCII-arvo on suurempi kuin 47 ja pienempi kuin 58, se tarkoittaa, että se on numero, ja palaamme 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.")

Tämä johtaa:

Yes, the string contains a number.

Tarkista, sisältääkö merkkijono numeron isnumeric()

- isnumeric() toiminto palaa True jos syötemerkkijono sisältää vain numeroita, muussa tapauksessa se palauttaa 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())

Tämä johtaa:

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

Huomautus: - isnumeric() toiminto ei toimi odotetulla tavalla negatiivisia tai kelluvia lukuja. Jos välitämme merkkijonon, jossa on vain negatiivisia numeroita tai kelluvia lukuja, se palaa False, koska - ja . negatiivisiin lukuihin ja liukuihin liittyvät merkit ovat todellakin, eivät numeroita.

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

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

Koska merkit ovat kuitenkin vain merkkijonoja, joiden pituus on 1 Pythonissa, voit iteroida merkkejä ja käyttää isnumeric() tarkistaaksesi, ovatko ne numeroita:

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

Tarkista, sisältääkö merkkijono Numeron ja isdigit()

- isdigit() toiminto tarkistaa, ovatko kaikki merkkijonon merkit numeroita. Jos kyllä ​​- se palaa True, ja jos ei, se palaa False. Jälleen, koska merkit ovat vain merkkijonoja, joiden pituus on 1 Pythonissa, tätä menetelmää voidaan käyttää silmukassa jokaiselle merkille:

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

Huomautus: - isdigit() menetelmä toimii vain samalla tavalla kuin isnumeric(), ja jos annat sille merkkijonon, joka sisältää kelluvan tai negatiivisen luvun, False palautetaan, koska erikoismerkit eivät ole numeroita. Hahmotasolla kuitenkin, jos yhtä kauan True arvo riittää määrittämään, sisältääkö merkkijono numeron – se on sovellettavissa.

Ero isnumeric()- ja isdigit()-funktioiden välillä?

Joten, mikä on ero isnumeric() ja isdigit()? Kun ollaan siinä – entä isdecimal()?

  • isnumeric() tarkistaa, onko jokin merkki a unicode-esitys a numeerinen arvo (joka sisältää roomalaiset numerot, yläindeksit, alaindeksit ja murtoluvut)
  • isdigit() tarkistaa, onko jokin merkki a unicode-numero (joka ei sisällä roomalaisia ​​numeroita, mutta sisältää ylä-/alaindeksit ja murtoluvut)
  • isdecimal() tarkistaa, onko jokin merkki a desimaalinumero (joka palaisi False kaikkeen, mikä ei ole 0..9 pohjassa 10)

isnumeric() on laajin menetelmä, kun taas isdecimal() on kapein näiden kolmen välillä.

Tarkista, sisältääkö merkkijono numeron käyttämällä map() ja any()

- map() toiminto suorittaa tarjotun toiminnon jokaiselle karttafunktiossa välitetyn iteroitavan elementille. Jokainen iteroitavan elementti välitetään funktiolle parametrina:

map(function, iterable)

- function suoritetaan jokaiselle kohteelle iterable. Tämä mahdollistaa erittäin joustavan ja tehokkaan logiikan, jota rajoittaa vain laajuus function soitat syötteeseen! Metodi palauttaa a map esimerkki, joka voidaan helposti muuttaa muiksi kokoelmiksi, kuten luetteloksi tai joukoksi.

Voimme kirjoittaa funktion, joka palauttaa loogisen arvon, joka ilmaisee, onko merkki numero, ja map() kutsu johtaa siten loogisten arvojen luetteloon.

- any() Tuotto True jos jokin ohitetun iteroitavan elementti on True, muuten se palaa False.

Yhdistämällä nämä kaksi yhteen – voimme luoda korkean tason, lyhyen käsikirjoituksen ja abstraktin for-silmukan:

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)

Tämä johtaa:

Is there a number present? True

Jos funktiosi on yksilinjainen, sitä ei tarvitse purkaa nimettynä funktiona. Voit kirjoittaa anonyymin lambda -toiminto sen sijaan lyhyyden vuoksi:

Tutustu käytännönläheiseen, käytännölliseen Gitin oppimisoppaaseemme, jossa on parhaat käytännöt, alan hyväksymät standardit ja mukana tuleva huijauslehti. Lopeta Git-komentojen googlailu ja oikeastaan oppia se!

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)

Tästä seuraa myös:

Is there any number present? True

Tarkista, sisältääkö merkkijono numeron Pythonissa säännöllisillä lausekkeilla

Säännölliset lausekkeet ovat hakumalleja suunniteltu vastaamaan syöttötekstiä. Ne ovat joustavia ja luonteensa vuoksi – voit kirjoittaa mielivaltaisen määrän ilmaisuja samalle kuviolle etsittäväksi sekä peittää minkä tahansa kuvittelemasi kuvion.

Pythonin re moduulia käytetään tekstin kirjoittamiseen, kokoamiseen ja yhdistämiseen säännöllisiin lausekkeisiin. Se paljastaa erilaisia ​​menetelmiä, kuten match() mikä vastaa sitä, alkaako merkkijono kuviolla, search() joka löytää ensimmäisen mahdollisesti useiden osumien esiintymisen merkkijonosta, ja findall() joka tarkistaa kaikki tapahtumat.

Huomautus: Kaikki kolme menetelmää hyväksyvät a pattern ja search argumentti ja suorita haku pattern vuonna search merkkijono.

Kuvio, joka tunnistaa a numero 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() method palauttaa a re.Match objekti, joka sisältää löydetyn osuman sekä aloitus- ja loppuindeksit:


Objekti voidaan arvioida loogiseksi arvoksi sen perusteella, onko se a re.Match esine tai None. Tästä seuraa:

Is there any number present? Yes

Toisin kuin search() menetelmällä, findall() menetelmä palauttaa kaikki kuvion esiintymät ensimmäisen sijasta:

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

Tämä johtaa:

Is there any number present? Yes

benchmarking

Entä suorituskyky? Jos purat logiikan ja leikkaat tarpeettomat osat rajoittamalla menetelmät vain tuloksen palauttamiseen, voit helposti verrata niitä toisiinsa samalla syötteellä:

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

Tämä johtaa:

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)

Yleensä for-loop-lähestymistavat toimivat suunnilleen samaan aikaan, ja tietyt menetelmät aiheuttavat vain vähän lisäkustannuksia. Lambda kanssa any() on defacto hitain (paljon redundantteja operaatioita, koska luettelo muunnetaan luetteloksi ja sen jälkeen pienennetään), kun taas Säännöllisillä lausekkeilla oli nopein suoritusaika pienimmällä varianssilla (ne ovat jatkuvasti nopeita).

Pidemmissä syöttöteksteissä kuitenkin korostuvat kunkin eri lähestymistavan aikamonimutkaisuus, erityisesti riippuen täsmäävien numeroiden määrästä (ovatko numerot yhteisiä vai eivät):

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) 

Ensimmäinen merkkijono luo satunnaisen sekvenssin, jossa on suunnilleen yhtä suuri määrä numeroita ja merkkejä, kun taas jälkimmäinen on vain merkkijono, jonka lopussa on yksi numero (pahin aika monimutkaisuus):

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

Pienellä osumien määrällä – Säännölliset lausekkeet ovat tehokkaimpia. Monilla osumilla lambda-toiminto on tehokkain, ja se säilyttää ajan monimutkaisuuden riippumatta siitä, onko syötteellä monta osumaa vai yksi. Suurin haittapuoli (reduntiivinen laskenta, kun osumaprosentti on alhainen) muutetaan sen päävahvuudeksi, koska redundanssi tekee siitä vakaan syöttämisen.

Yhteenveto

Tässä opetusohjelmassa tarkastelimme useita tapoja tarkistaa, sisältääkö Pythonin merkkijono vähintään yhden merkin. Olemme käyneet katsomassa ord(), isnumeric(), isdigit() ja isdecimal() funktio, sekä kuinka abstrakti tämä logiikka lambda-funktiokutsulla käyttämällä map() ja any(). Sitten tutkimme säännöllisiä lausekkeita ja vertailimme lähestymistapoja vaihtelevalla syötteellä.

Aikaleima:

Lisää aiheesta Stackabus