Wie kann ich überprüfen, ob eine Zeichenfolge Buchstaben aus dem Alphabet enthält?

84

Was ist die beste reine Python-Implementierung, um zu überprüfen, ob eine Zeichenfolge ALLE Buchstaben aus dem Alphabet enthält?

string_1 = "(555).555-5555"
string_2 = "(555) 555 - 5555 ext. 5555

Wo string_1würde Falseich zurückkehren, wenn ich keine Buchstaben des Alphabets darin string_2hätte, und würde zurückkehren, Trueweil ich Buchstaben habe.

Justin Papez
quelle
2
Sollte dies nur auf das englische A / Z-Alphabet beschränkt sein? Sollten "Sonderzeichen" aus anderen Alphabeten wie Deutsch berücksichtigt werden?
Kotch
Gibt es eine Chance, dass Sie Unicode erhalten? Oder einfach nur asiatische Buchstaben?
KobeJohn
Nettes Timing dort :) Wie auch immer, sehen Sie sich diese ähnliche Frage an, wenn Sie Hilfe beim Testen von Zeichenfolgen mit Unicode-Zeichen benötigen.
KobeJohn
1
Beschränkt auf das englische A / Z-Alphabet und nur einfache ASCII-Buchstaben :)
Justin Papez

Antworten:

123

Regex sollte ein schneller Ansatz sein:

re.search('[a-zA-Z]', the_string)
JBernardo
quelle
1
Vielen Dank, JBernado, das habe ich letztendlich getan und es funktioniert einwandfrei für das, was ich tun muss.
Justin Papez
34
Regex scheint sicherlich ein bisschen übertrieben. any(c.isalpha() for c in string_1)ist köstlich Pythonic.
Jollywatt
5
@ Joseph Nein, ist es nicht. Dieser reguläre Ausdruck ist weitaus besser lesbar als Ihr Ausdruck. Was bedeutet das isalphaüberhaupt? Dies hat ein völlig anderes Verhalten beim Vergleich von Python 2 mit Python 3. Ist Chinesisch Teil des Alphabets? Wenn nicht, stimmen Sie es blind mit Ihrem Generator auf Python 3 ab (oder Python 2 für Unicode-Strings!). Wenn Sie Pythonic wollen , hier ist es : Simple is better than complex.. Und überprüfen Sie den obigen Kommentar von OP: Er möchte, dass nur das römische Alphabet übereinstimmt.
JBernardo
1
Ich denke, Josephs Antwort ist perfekt lesbar und sicherlich schneller als ein zusätzlicher Import. Außerdem müssen Sie sich nicht an die Reihenfolge der Argumente in re.search erinnern
Hinton
11
Falls sich jemand fragt, wie hoch der Rückgabewert ist, erhalten Sie ein MatchObjekt, wenn eine Übereinstimmung vorliegt oder Nonenicht. Das ist also mit einem if re.search(...Muster kompatibel .
Srini
76

Wie wäre es mit:

>>> string_1 = "(555).555-5555"
>>> string_2 = "(555) 555 - 5555 ext. 5555"
>>> any(c.isalpha() for c in string_1)
False
>>> any(c.isalpha() for c in string_2)
True
DSM
quelle
Wäre set(string_1)effizienter?
Rik Poggi
1
@ Rik. Du meinst, string_1 vor dem Testen in eine Menge umzuwandeln? Nein, es wird nicht effizienter sein. Das wird garantiert mindestens einmal mit allen Zeichen umgehen, während ich glaube, dass jede Funktion kurzgeschlossen wird (stoppt), wenn sie auf das erste falsche trifft.
KobeJohn
Dieser Code ist etwas langsam, da ein Funktionsaufruf pro Zeichen erforderlich ist. Das Konvertieren in setkann Funktionsaufrufe reduzieren oder nicht, erhöht jedoch den Overhead.
JBernardo
2
@JBernardo: timeit schlägt vor, dass es ungefähr eine Größenordnung langsamer ist als ein kompilierter regulärer Ausdruck und nur etwa 66% mehr Zeit benötigt als ein nicht kompilierter. Das liegt innerhalb meiner Grenzen "Ich hasse reguläre Ausdrücke".
DSM
1
Sicher: und wenn Sie "(555) .555-5555 ext. 5555" * 1000 verwenden, sind Sie aufgrund des Kurzschlusses wieder auf vergleichbare Geschwindigkeiten eingestellt. Ich schreibe lieber in Python als in regulären Ausdrücken, die ich nur schwer debuggen kann, wenn sie nicht trivial sind, und ich werde das Schreiben von klarem Python nicht aufgeben, es sei denn, die Leistungsanforderungen erfordern dies.
DSM
27

Sie können islower()Ihre Zeichenfolge verwenden, um festzustellen, ob sie (unter anderem) Kleinbuchstaben enthält. ores mit isupper()auch zu überprüfen, ob einige Großbuchstaben enthält:

unten: Buchstaben in der Zeichenfolge: Test ergibt true

>>> z = "(555) 555 - 5555 ext. 5555"
>>> z.isupper() or z.islower()
True

unten: keine Buchstaben in der Zeichenfolge: Test ergibt falsch.

>>> z= "(555).555-5555"
>>> z.isupper() or z.islower()
False
>>> 

Nicht zu verwechseln, isalpha()was Truenur zurückgibt , wenn alle Zeichen Buchstaben sind, was nicht das ist, was Sie wollen.

Beachten Sie, dass Barms Antwort meine gut vervollständigt, da meine den gemischten Fall nicht gut behandelt.

Jean-François Fabre
quelle
3
Ich mag es, dass dies testet, ob es Buchstaben enthält, nicht nur testet, ob die Eingabe ALLE Buchstaben ist.
Cornbeetle
@Cornbeetle ja, diese Art beantwortet wirklich die Frage nach all den Jahren, danke
Jean-François Fabre
Sehr schöne Art, das auszudrücken. Wie ist es in Bezug auf Effizienz? besser als Regex?
PNV
Es sind keine Python-Schleifen beteiligt, daher ist die Effizienz gut. Ich habe nicht mit Regex verglichen, aber ich nehme an, es ist etwas schneller, speziell für die Initialisierungsphase, da kein Regex zu kompilieren ist
Jean-François Fabre
13

Ich mochte die Antwort von @ jean-françois-fabre , aber sie ist unvollständig.
Sein Ansatz wird funktionieren, aber nur, wenn der Text nur Klein- oder Großbuchstaben enthält:

>>> text = "(555).555-5555 extA. 5555"
>>> text.islower()
False
>>> text.isupper()
False

Der bessere Ansatz besteht darin, zuerst die Zeichenfolge in Groß- oder Kleinbuchstaben zu schreiben und dann zu überprüfen.

>>> string1 = "(555).555-5555 extA. 5555"
>>> string2 = '555 (234) - 123.32   21'

>>> string1.upper().isupper()
True
>>> string2.upper().isupper()
False
Barm
quelle
8

Sie können reguläre Ausdrücke wie folgt verwenden:

import re

print re.search('[a-zA-Z]+',string)
shibly
quelle
2

Ich habe jede der oben genannten Methoden getestet, um festzustellen, ob Alphabete in einer bestimmten Zeichenfolge enthalten sind, und die durchschnittliche Verarbeitungszeit pro Zeichenfolge auf einem Standardcomputer ermittelt.

~ 250 ns für

import re

~ 3 µs für

re.search('[a-zA-Z]', string)

~ 6 µs für

any(c.isalpha() for c in string)

~ 850 ns für

string.upper().isupper()


Im Gegensatz zu angeblich dauert das Importieren von re vernachlässigbar lange, und das Suchen mit re dauert nur etwa die Hälfte der Zeit , verglichen mit dem Iterieren von isalpha (), selbst für eine relativ kleine Zeichenfolge.
Daher wäre re für größere Saiten und größere Zählungen wesentlich effizienter.

Aber das Konvertieren eines Strings in einen Fall und das Überprüfen des Falls (dh eines der oberen (). Isupper () oder unteren (). Islower () ) gewinnt hier. In jeder Schleife ist es deutlich schneller als re.search () und erfordert nicht einmal zusätzliche Importe.

Mihir Verma
quelle
1
Sie können den regulären Ausdruck auch für eine weitere Optimierung kompilieren. alpha_regex = re.compile ('[a-zA-Z]') später alpha_regex.search (Zeichenfolge)
Behdad Forghani
Ganz zu schweigen davon, dass isalpha () für mehrere Sprachen nicht gut funktioniert. Ich habe danach gesucht, weil ich überprüfen wollte, ob eine Zeichenfolge, von der erwartet wird, dass sie koreanisch ist, englische Buchstaben enthält, und die Methode isalpha () für jede koreanische Zeichenfolge True zurückgibt.
Chan Woo
0

Sie können dies auch zusätzlich tun

import re
string='24234ww'
val = re.search('[a-zA-Z]+',string) 
val[0].isalpha() # returns True if the variable is an alphabet
print(val[0]) # this will print the first instance of the matching value

Beachten Sie auch, dass, wenn die Variable val None zurückgibt. Das heißt, die Suche hat keine Übereinstimmung gefunden

Ronald Saunfe
quelle