@JG: Ich habe gtk.Entry () und ich möchte multiplizieren float eingegeben.
Jan Tojnar
1
@JanTojnar verwendet die re.sub-Methode gemäß Antwort zwei und listet explizit auf, welche Zeichen zu behalten sind, z. B. re.sub ("[^ 0123456789 \.]", "", "Poo123.4and5fish")
Roger Heathcote
Antworten:
112
In Python 2. * ist der mit Abstand schnellste Ansatz die .translateMethode:
string.maketranserstellt eine Übersetzungstabelle (eine Zeichenfolge mit der Länge 256), die in diesem Fall dieselbe ist wie ''.join(chr(x) for x in range(256))(nur schneller zu erstellen ;-). .translatewendet die Übersetzungstabelle an (die hier irrelevant ist, da sie im allWesentlichen Identität bedeutet) UND löscht Zeichen, die im zweiten Argument vorhanden sind - dem Schlüsselteil.
.translatefunktioniert sehr unterschiedlich auf Unicode - Strings (und Strings in Python 3 - ich tue Wunsch Fragen festgelegt , welche Hauptrelease von Python von Interesse ist!) - das nicht ganz einfach, das nicht ganz schnell, aber immer noch recht brauchbar.
Zurück zu 2. * ist der Leistungsunterschied beeindruckend ...:
$ python -mtimeit -s'import string; all=string.maketrans("", ""); nodig=all.translate(all, string.digits); x="aaa12333bb445bb54b5b52"''x.translate(all, nodig)'1000000 loops, best of 3:1.04 usec per loop
$ python -mtimeit -s'import re; x="aaa12333bb445bb54b5b52"''re.sub(r"\D", "", x)'100000 loops, best of 3:7.9 usec per loop
Das 7-8-fache zu beschleunigen ist kaum Erdnuss, daher ist die translateMethode es wert, sie zu kennen und anzuwenden. Der andere beliebte Nicht-RE-Ansatz ...:
$ python -mtimeit -s'x="aaa12333bb445bb54b5b52"''"".join(i for i in x if i.isdigit())'100000 loops, best of 3:11.5 usec per loop
ist 50% langsamer als RE, daher .translateschlägt der Ansatz ihn um mehr als eine Größenordnung.
In Python 3 oder für Unicode müssen Sie .translateeine Zuordnung (mit Ordnungszahlen, nicht Zeichen direkt als Schlüssel) übergeben, die Nonefür das zurückgibt, was Sie löschen möchten. Hier ist eine bequeme Möglichkeit, dies auszudrücken, um "alles außer" ein paar Zeichen zu löschen:
import string
classDel:def __init__(self, keep=string.digits):
self.comp = dict((ord(c),c)for c in keep)def __getitem__(self, k):return self.comp.get(k)
DD =Del()
x='aaa12333bb445bb54b5b52'
x.translate(DD)
emittiert auch '1233344554552'. Wenn wir dies jedoch in xx.py einfügen, haben wir ...:
$ python3.1-mtimeit -s'import re; x="aaa12333bb445bb54b5b52"''re.sub(r"\D", "", x)'100000 loops, best of 3:8.43 usec per loop
$ python3.1-mtimeit -s'import xx; x="aaa12333bb445bb54b5b52"''x.translate(xx.DD)'10000 loops, best of 3:24.3 usec per loop
... was zeigt, dass der Leistungsvorteil für diese Art von "Lösch" -Aufgaben verschwindet und zu einem Leistungsabfall wird.
@sunqiang, ja, absolut - es gibt einen Grund, warum Py3k anstelle von Byte-Strings wie in Py2 zu Unicode als THE-Text-String-Typ gewechselt ist - der gleiche Grund, warum Java und C # immer das gleiche Mem "String bedeutet Unicode" hatten ... Vielleicht etwas Overhead, aber VIEL bessere Unterstützung für fast alles andere als Englisch! -).
Alex Martelli
29
x.translate(None, string.digits)führt tatsächlich dazu 'aaabbbbbb', was das Gegenteil von dem ist, was beabsichtigt ist.
Tom Dalling
4
In Anlehnung an die Kommentare von Tom Dalling enthält Ihr erstes Beispiel alle unerwünschten Zeichen - macht das Gegenteil von dem, was Sie gesagt haben.
Chris Johnson
3
@ RyanB.Lynch et al., Der Fehler lag bei einem späteren Editor und zwei anderen Benutzern, die diese Bearbeitung genehmigt haben , was in der Tat völlig falsch ist. Zurückgesetzt.
Nick T
1
übergeordnetes alleingebautes ... da bin ich mir nicht sicher!
Andy Hayden
197
Verwenden Sie re.subwie folgt:
>>>import re
>>> re.sub('\D','','aas30dsa20')'3020'
\D Entspricht einem nichtstelligen Zeichen, ersetzt der obige Code im Wesentlichen jedes nichtstellige Zeichen für die leere Zeichenfolge.
Oder Sie können filterwie folgt verwenden (in Python 2):
>>> filter(str.isdigit,'aas30dsa20')'3020'
Da in Python 3 filterein Iterator anstelle von a zurückgegeben wird list, können Sie stattdessen Folgendes verwenden:
Es ist böse in solch einer einfachen Aufgabe, die zweite ist die beste, die ich denke, weil 'ist ...' Methoden für Strings am schnellsten sind.
f0b0s
Ihr Filterbeispiel ist auf py2k
SilentGhost
2
@ f0b0s-iu9-info: hast du es geplant? auf meiner Maschine (py3k) ist re doppelt so schnell wie Filter mit isdigit, Generator mit isdigtist auf halbem Weg dazwischen
SilentGhost
@ SilentGhost: Danke, ich habe IDLE von py2k verwendet. Es ist jetzt behoben.
nur in py2k, in py3k gibt es einen Generator zurück
SilentGhost
konvertieren strzu list, um sicherzustellen, dass es sowohl auf py2 als auch auf py3 funktioniert:''.join(filter(lambda x: x.isdigit(), list("dasdasd2313dsa")))
Ich bekomme ein TypeError: translate () nimmt genau ein Argument (2 angegeben). Warum diese Frage in ihrem gegenwärtigen Zustand positiv bewertet wurde, ist ziemlich frustrierend.
Bobort
Die Übersetzung wurde von Python 2 in 3 geändert. Die Syntax, die diese Methode in Python 3 verwendet, lautet x.translate (str.maketrans ('', '', string.digits)) und x.translate (str.maketrans ('', ''). , string.ascii_letters)). Keiner dieser Streifen Leerraum. Ich würde diesen Ansatz nicht mehr wirklich empfehlen ...
ZaxR
5
Die Op erwähnt in den Kommentaren, dass er die Dezimalstelle behalten möchte. Dies kann mit der Methode re.sub (gemäß der zweiten und meiner Meinung nach besten Antwort) erfolgen, indem die zu behaltenden Zeichen explizit aufgelistet werden, z
In meinem Code überprüfe ich die Anzahl der Punkte in der Eingabezeichenfolge und erhalte einen Fehler, wenn dieser mehr als 1 beträgt.
Roger Heathcote
4
Eine schnelle Version für Python 3:
# xx3.pyfrom collections import defaultdict
import string
_NoneType= type(None)def keeper(keep):
table = defaultdict(_NoneType)
table.update({ord(c): c for c in keep})return table
digit_keeper = keeper(string.digits)
Hier ist ein Leistungsvergleich mit Regex:
$ python3.3-mtimeit -s'import xx3; x="aaa12333bb445bb54b5b52"''x.translate(xx3.digit_keeper)'1000000 loops, best of 3:1.02 usec per loop
$ python3.3-mtimeit -s'import re; r = re.compile(r"\D"); x="aaa12333bb445bb54b5b52"''r.sub("", x)'100000 loops, best of 3:3.43 usec per loop
Für mich ist es also etwas mehr als dreimal schneller als Regex. Es ist auch schneller als class Deloben, da defaultdictalle Suchvorgänge in C und nicht in (langsamem) Python ausgeführt werden. Hier ist diese Version auf meinem System zum Vergleich.
$ python3.3-mtimeit -s'import xx; x="aaa12333bb445bb54b5b52"''x.translate(xx.DD)'100000 loops, best of 3:13.6 usec per loop
@ SilentGhost es ist mein Missverständnis. hatte es korrigiert danke :)
Gant
Eigentlich glaube ich nicht, dass Sie mit dieser Methode "join" verwenden müssen. filter(lambda x: x.isdigit(), s)hat gut für mich funktioniert. ... oh, das liegt daran, dass ich Python 2.7 verwende.
Warum wiederholen Sie die beiden Methoden zweimal? Und können Sie beschreiben, wie sich Ihre Antwort von der akzeptierten unterscheidet?
Jan Tojnar
Beide ergeben die gleiche Ausgabe. Aber ich möchte nur zeigen, dass Join die Submethode in den Ergebnissen schneller ist.
AnilReddy
Sie tun es nicht, Ihr Code macht das Gegenteil. Und Sie haben auch vier Messungen, aber nur zwei Methoden.
Jan Tojnar
1
Sie können jedes Zeichen lesen. Wenn es sich um eine Ziffer handelt, nehmen Sie sie in die Antwort auf. Mit dieser str.isdigit()Methode können Sie feststellen, ob ein Zeichen eine Ziffer ist.
your_input ='12kjkh2nnk34l34'
your_output =''.join(c for c in your_input if c.isdigit())print(your_output)# '1223434'
Antworten:
In Python 2. * ist der mit Abstand schnellste Ansatz die
.translate
Methode:string.maketrans
erstellt eine Übersetzungstabelle (eine Zeichenfolge mit der Länge 256), die in diesem Fall dieselbe ist wie''.join(chr(x) for x in range(256))
(nur schneller zu erstellen ;-)..translate
wendet die Übersetzungstabelle an (die hier irrelevant ist, da sie imall
Wesentlichen Identität bedeutet) UND löscht Zeichen, die im zweiten Argument vorhanden sind - dem Schlüsselteil..translate
funktioniert sehr unterschiedlich auf Unicode - Strings (und Strings in Python 3 - ich tue Wunsch Fragen festgelegt , welche Hauptrelease von Python von Interesse ist!) - das nicht ganz einfach, das nicht ganz schnell, aber immer noch recht brauchbar.Zurück zu 2. * ist der Leistungsunterschied beeindruckend ...:
Das 7-8-fache zu beschleunigen ist kaum Erdnuss, daher ist die
translate
Methode es wert, sie zu kennen und anzuwenden. Der andere beliebte Nicht-RE-Ansatz ...:ist 50% langsamer als RE, daher
.translate
schlägt der Ansatz ihn um mehr als eine Größenordnung.In Python 3 oder für Unicode müssen Sie
.translate
eine Zuordnung (mit Ordnungszahlen, nicht Zeichen direkt als Schlüssel) übergeben, dieNone
für das zurückgibt, was Sie löschen möchten. Hier ist eine bequeme Möglichkeit, dies auszudrücken, um "alles außer" ein paar Zeichen zu löschen:emittiert auch
'1233344554552'
. Wenn wir dies jedoch in xx.py einfügen, haben wir ...:... was zeigt, dass der Leistungsvorteil für diese Art von "Lösch" -Aufgaben verschwindet und zu einem Leistungsabfall wird.
quelle
x.translate(None, string.digits)
führt tatsächlich dazu'aaabbbbbb'
, was das Gegenteil von dem ist, was beabsichtigt ist.all
eingebautes ... da bin ich mir nicht sicher!Verwenden Sie
re.sub
wie folgt:\D
Entspricht einem nichtstelligen Zeichen, ersetzt der obige Code im Wesentlichen jedes nichtstellige Zeichen für die leere Zeichenfolge.Oder Sie können
filter
wie folgt verwenden (in Python 2):Da in Python 3
filter
ein Iterator anstelle von a zurückgegeben wirdlist
, können Sie stattdessen Folgendes verwenden:quelle
isdigit
, Generator mitisdigt
ist auf halbem Weg dazwischenr
für rohe Saite verwenden:re.sub(r"\D+", "", "aas30dsa20")
Eine weitere Generatorvariante.
quelle
Sie können Filter verwenden:
Auf python3.0 musst du dich dem anschließen (irgendwie hässlich :()
quelle
str
zulist
, um sicherzustellen, dass es sowohl auf py2 als auch auf py3 funktioniert:''.join(filter(lambda x: x.isdigit(), list("dasdasd2313dsa")))
in Anlehnung an Bayers Antwort:
quelle
-
es sich nicht um eine Ziffer handelt.Sie können dies einfach mit Regex tun
quelle
löscht alle Ziffern aus der Zeichenfolge. Gehen Sie folgendermaßen vor, um Buchstaben zu löschen und die Ziffern beizubehalten:
quelle
TypeError
: translate () nimmt genau ein Argument (2 angegeben). Warum diese Frage in ihrem gegenwärtigen Zustand positiv bewertet wurde, ist ziemlich frustrierend.Die Op erwähnt in den Kommentaren, dass er die Dezimalstelle behalten möchte. Dies kann mit der Methode re.sub (gemäß der zweiten und meiner Meinung nach besten Antwort) erfolgen, indem die zu behaltenden Zeichen explizit aufgelistet werden, z
quelle
Eine schnelle Version für Python 3:
Hier ist ein Leistungsvergleich mit Regex:
Für mich ist es also etwas mehr als dreimal schneller als Regex. Es ist auch schneller als
class Del
oben, dadefaultdict
alle Suchvorgänge in C und nicht in (langsamem) Python ausgeführt werden. Hier ist diese Version auf meinem System zum Vergleich.quelle
Verwenden Sie einen Generatorausdruck:
quelle
''.join(n for n in foo if n.isdigit())
Hässlich aber funktioniert:
quelle
list(s)
?filter(lambda x: x.isdigit(), s)
hat gut für mich funktioniert. ... oh, das liegt daran, dass ich Python 2.7 verwende.Ich hatte beobachtet, dass Join schneller als Sub ist.
quelle
Sie können jedes Zeichen lesen. Wenn es sich um eine Ziffer handelt, nehmen Sie sie in die Antwort auf. Mit dieser
str.isdigit()
Methode können Sie feststellen, ob ein Zeichen eine Ziffer ist.quelle
Kein Einzeiler, aber sehr einfach:
quelle
Ich habe das benutzt.
'letters'
sollte alle Buchstaben enthalten, die Sie loswerden möchten:Output = Input.translate({ord(i): None for i in 'letters'}))
Beispiel:
Input = "I would like 20 dollars for that suit" Output = Input.translate({ord(i): None for i in 'abcdefghijklmnopqrstuvwxzy'})) print(Output)
Ausgabe:
20
quelle