Überprüfen Sie, ob String in Python eine Zahl enthält

Einleitung

Ob Sie ein Verifizierungsskript für Benutzereingaben oder ein Anmeldeformular erstellen, das Benutzer auffordert, ein Zeichen in ein Passwort einzufügen – die Überprüfung, ob eine Zeichenfolge ein Zeichen enthält, ist kein ungewöhnlicher Vorgang.

In diesem Tutorial werfen wir einen Blick auf die vielen Möglichkeiten, wie Sie in Python überprüfen können, ob eine Zeichenfolge eine Ziffer/Zahl enthält, einschließlich eines Benchmarks für den am Ende effizientesten Ansatz.

Überprüfen Sie, ob die Zeichenfolge in Python eine Zahl enthält

Es gibt mehrere Möglichkeiten zu überprüfen, ob a Charakter ist eine Zahl (ord(), isnumeric(), isdigit()), die Sie mit einer for-Schleife koppeln können, um nach mindestens einem einzigen positiven Treffer zu suchen. Alternativ können Sie reguläre Ausdrücke als allgemeine Mustervergleicher verwenden, die flexibel und leistungsstark sind und für die Anwendung auf große Textkorpusse konzipiert sind. Endlich – Sie können es immer map() Jedes Zeichen erhält eine bedingte Anweisung und kehrt zurück True is any() davon ergeben sich True.

Bei der Wahl zwischen diesen sollten die Effizienz der Methoden, die Ausführlichkeit und der Codierungsstil sowie die mit dem Vorgang verbundenen vor- oder nachgelagerten Aufgaben berücksichtigt werden.

Überprüfen Sie mit ord(), ob der String eine Zahl enthält

Das ord() Die Funktion nimmt ein Zeichen und gibt es zurück ASCII Wert:

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

Der ASCII-Wert von 0 ist 48 und der ASCII-Wert von 9 ist 57. Jede Zahl dazwischen wird im weiteren Sinne einen ASCII-Wert zwischen 48 und 57 haben. Um nun zu überprüfen, ob die Zeichenfolge eine Zahl enthält, durchlaufen wir die gesamte Eingabezeichenfolge und überprüfen den ASCII-Wert jedes Zeichens. Wenn der ASCII-Wert mehr als 47 und weniger als 58 ist, bedeutet dies, dass es sich um eine Zahl handelt, und wir kehren zurück 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.")

Das führt zu:

Yes, the string contains a number.

Überprüfen Sie mit isnumeric(), ob der String eine Zahl enthält

Das isnumeric() Funktion kehrt zurück True Wenn die Eingabezeichenfolge nur Zahlen enthält, wird andernfalls zurückgegeben 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())

Das führt zu:

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

Hinweis: Das isnumeric() Die Funktion verhält sich nicht wie erwartet negative oder Float-Zahlen. Wenn wir eine Zeichenfolge nur mit negativen oder Gleitkommazahlen übergeben, wird sie zurückgegeben False, Weil die - und . Zeichen, die mit negativen Zahlen und Gleitkommazahlen verknüpft sind, sind in der Tat keine Zahlen.

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

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

Da Zeichen in Python jedoch nur Zeichenfolgen der Länge 1 sind, können Sie Zeichen durchlaufen und verwenden isnumeric() um zu prüfen, ob es sich um eine Zahl handelt:

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

Überprüfen Sie mit isdigit(), ob der String eine Zahl enthält

Das isdigit() Die Funktion prüft, ob alle Zeichen in einer Zeichenfolge Ziffern sind. Wenn ja, kehrt es zurück True, und wenn nicht, wird es zurückgegeben False. Da Zeichen in Python wiederum nur Zeichenfolgen der Länge 1 sind, kann diese Methode in einer Schleife für jedes Zeichen verwendet werden:

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

Hinweis: Das isdigit() Methode verhält sich nur auf die gleiche Weise wie isnumeric(), und wenn Sie ihm eine Zeichenfolge übergeben, die eine Gleitkommazahl oder eine negative Zahl enthält, False wird zurückgegeben, da es sich bei den Sonderzeichen nicht um Zahlen handelt. Allerdings auf Charakterebene, wenn auch nur eine True Der Wert reicht aus, um festzustellen, ob die Zeichenfolge eine Zahl enthält – er ist anwendbar.

Unterschied zwischen isnumeric() und isdigit()?

Also, was ist der Unterschied zwischen isnumeric() und isdigit()? Wenn wir schon dabei sind – wie wär’s mit isdecimal()?

  • isnumeric() prüft, ob ein Zeichen ein ist Unicode-Darstellung einer Zahlenwert (einschließlich römischer numerischer Darstellungen, hochgestellter, tiefgestellter und gebrochener Zahlen)
  • isdigit() prüft, ob ein Zeichen ein ist Unicode-Ziffer (was keine römischen numerischen Darstellungen einschließt, aber hochgestellte/tiefgestellte Zeichen und Brüche)
  • isdecimal() prüft, ob es sich bei einem Zeichen um ein handelt Dezimalstelle (was zurückkehren würde False für alles, was nicht so ist 0..9 in Basis 10)

isnumeric() ist die umfassendste Methode, während isdecimal() ist die schmalste der drei.

Überprüfen Sie mit map() und any(), ob der String eine Zahl enthält

Das map() Die Funktion führt die bereitgestellte Funktion für jedes Element des in der Map-Funktion übergebenen Iterables aus. Jedes Element einer Iterable wird als Parameter an die Funktion übergeben:

map(function, iterable)

Das function wird für jedes Element des ausgeführt iterable. Dies ermöglicht eine sehr flexible und leistungsstarke Logik, die nur durch den Umfang der Logik begrenzt ist function Du rufst den Eingang an! Die Methode gibt a zurück map Instanz, die problemlos in andere Sammlungen wie eine Liste oder einen Satz umgewandelt werden kann.

Wir können eine Funktion schreiben, die einen booleschen Wert zurückgibt, der angibt, ob ein Zeichen eine Zahl ist, und den map() Der Aufruf führt somit zu einer Liste boolescher Werte.

Das any() Rückgabe True wenn irgendein Element der übergebenen Iterable ist True, andernfalls wird es zurückgegeben False.

Wenn wir diese beiden aneinanderreihen, können wir ein kurzes Skript auf hoher Ebene erstellen und die for-Schleife abstrahieren:

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)

Das führt zu:

Is there a number present? True

Wenn es sich bei Ihrer Funktion um eine Einzeilerfunktion handelt, ist es nicht erforderlich, sie als benannte Funktion zu extrahieren. Sie können eine anonyme Nachricht schreiben Lambda-Funktion stattdessen der Kürze halber:

Sehen Sie sich unseren praxisnahen, praktischen Leitfaden zum Erlernen von Git an, mit Best Practices, branchenweit akzeptierten Standards und einem mitgelieferten Spickzettel. Hören Sie auf, Git-Befehle zu googeln und tatsächlich in Verbindung, um es!

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)

Dies führt auch zu:

Is there any number present? True

Überprüfen Sie mit regulären Ausdrücken, ob die Zeichenfolge in Python eine Zahl enthält

Reguläre Ausdrücke sind Suchmuster Entwickelt, um mit dem Eingabetext abgeglichen zu werden. Sie sind flexibel und aufgrund ihrer Natur – Sie können eine beliebige Anzahl von Ausdrücken für dasselbe zu suchende Muster schreiben und jedes erdenkliche nachvollziehbare Muster abdecken.

Pythons re Das Modul wird zum Schreiben, Kompilieren und Vergleichen von Text mit regulären Ausdrücken verwendet. Es stellt verschiedene Methoden offen, wie z match() was übereinstimmt, ob eine Zeichenfolge mit einem Muster beginnt, search() die das erste Vorkommen von möglicherweise vielen Übereinstimmungen in einer Zeichenfolge findet, und findall() die nach allen Vorkommnissen sucht.

Hinweis: Alle drei Methoden akzeptieren a pattern und search Argument und führen Sie eine Suche nach dem aus pattern der search String.

Das Muster, das a identifiziert Ziffer 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")

Das search() Methode gibt a zurück re.Match Objekt, das die gefundene Übereinstimmung sowie die Start- und Endindizes enthält:


Das Objekt kann basierend darauf, ob es sich um ein handelt, in einen booleschen Wert ausgewertet werden re.Match Objekt oder None. Das führt zu:

Is there any number present? Yes

im Gegensatz zu den search() Verfahren wird die findall() Die Methode gibt alle Vorkommen des Musters zurück, nicht nur das erste:

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

Das führt zu:

Is there any number present? Yes

Benchmarking

Wie sieht es mit der Leistung aus? Wenn Sie die Logik extrahieren und die unnötigen Teile kürzen und die Methoden auf die Rückgabe des Ergebnisses beschränken, können Sie sie problemlos mit derselben Eingabe miteinander vergleichen:

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

Das führt zu:

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)

Im Allgemeinen werden die For-Loop-Ansätze ungefähr zur gleichen Zeit ausgeführt, wobei die spezifischen Methoden nur wenig Overhead verursachen. Lambda mit any() ist de facto am langsamsten (viele redundante Vorgänge, da eine Liste in eine Liste konvertiert und dann reduziert wird), während reguläre Ausdrücke die schnellste Laufzeit mit der geringsten Varianz haben (sie sind durchweg schnell).

Bei längeren Eingabetexten wird jedoch die zeitliche Komplexität der einzelnen Ansätze deutlich, insbesondere abhängig von der Anzahl der übereinstimmenden Ziffern (ob Ziffern häufig vorkommen oder nicht):

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) 

Die erste Zeichenfolge generiert eine Zufallsfolge mit etwa der gleichen Anzahl von Ziffern und Zeichen, während die zweite Zeichenfolge nur aus Zeichen mit einer einzelnen Ziffer am Ende besteht (schlechteste Zeitkomplexität):

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

Bei einer geringen Anzahl von Treffern sind reguläre Ausdrücke am leistungsstärksten. Bei vielen Treffern ist der Lambda-Funktionsansatz der leistungsstärkste, und zwar behält seine zeitliche Komplexität unabhängig davon, ob die Eingabe viele oder einen Treffer hat. Der Hauptnachteil (redundante Berechnung bei niedriger Trefferquote) wird zu seiner Hauptstärke, da die Redundanz es robust gegenüber Eingaben macht.

Zusammenfassung

In diesem Tutorial haben wir uns mehrere Möglichkeiten angesehen, um zu überprüfen, ob eine Zeichenfolge in Python mindestens ein Zeichen enthält. Wir haben einen Blick darauf geworfen ord(), isnumeric(), isdigit() und isdecimal() Funktion sowie wie man diese Logik mit einem Lambda-Funktionsaufruf abstrahiert map() und any(). Anschließend untersuchten wir reguläre Ausdrücke und verglichen die Ansätze mit unterschiedlichen Eingaben.

Zeitstempel:

Mehr von Stapelmissbrauch