Teilen Sie Zeichenfolgen mit mehreren Wortbegrenzungszeichen in Wörter auf
Lesezeit: 10 Minuten
ooboo
Ich denke, was ich tun möchte, ist eine ziemlich häufige Aufgabe, aber ich habe keine Referenz im Internet gefunden. Ich habe Text mit Satzzeichen und möchte eine Liste der Wörter.
Aber Pythons str.split() funktioniert nur mit einem Argument, also habe ich alle Wörter mit Satzzeichen, nachdem ich mit Leerzeichen geteilt habe. Irgendwelche Ideen?
Pythons str.split() funktioniert auch ganz ohne Argumente
– Iwan Winogradow
8. Mai 2018 um 9:04 Uhr
Richie Hindle
Ein Fall, in dem reguläre Ausdrücke gerechtfertigt sind:
import re
DATA = "Hey, you - what are you doing here!?"
print re.findall(r"[\w']+", DATA)
# Prints ['Hey', 'you', 'what', 'are', 'you', 'doing', 'here']
Vielen Dank. Trotzdem interessiert – wie kann ich den in diesem Modul verwendeten Algorithmus implementieren? Und warum erscheint es nicht im Stringmodul?
– ooboo
29. Juni 2009 um 18:06 Uhr
Reguläre Ausdrücke können zunächst entmutigend sein, sind aber sehr mächtig. Der reguläre Ausdruck ‘\w+’ bedeutet “ein Wortzeichen (az usw.), das einmal oder mehrmals wiederholt wird”. Hier finden Sie ein HOWTO zu regulären Ausdrücken in Python: amk.ca/python/howto/regex
– Richie Hindle
4. Juli 2009 um 19:44 Uhr
Dies ist nicht die Antwort auf die Frage. Dies ist eine Antwort auf eine andere Frage, die zufällig für diese spezielle Situation funktioniert. Es ist, als würde jemand fragen: „Wie biege ich links ab“ und die am häufigsten gewählte Antwort lautete „Nehmen Sie die nächsten drei Rechtskurven“. Es funktioniert für bestimmte Kreuzungen, aber es gibt nicht die benötigte Antwort. Ironischerweise die Antwort ist in reeinfach nicht findall. Die Antwort unten geben re.split() ist überlegen.
– Jesse Dillon
9. September 2013 um 18:47 Uhr
@JesseDhillon “alle Teilzeichenfolgen nehmen, die aus einer Folge von Wortzeichen bestehen” und “auf alle Teilzeichenfolgen aufteilen, die aus einer Folge von Nichtwortzeichen bestehen” sind buchstäblich nur unterschiedliche Möglichkeiten, dieselbe Operation auszudrücken. Ich bin mir nicht sicher, warum Sie eine der Antworten überlegen nennen würden.
– Mark Amery
13. Juli 2015 um 17:51 Uhr
@TMWP: Der Apostoph bedeutet, dass ein Wort wie don't wird als ein einziges Wort behandelt und nicht aufgeteilt don und t.
– Richie Hindle
21. März 2017 um 14:48 Uhr
Schnell und schmutzig, aber perfekt für meinen Fall (meine Trennzeichen waren ein kleines, bekanntes Set)
– Andy Bäcker
1. September 2012 um 9:34 Uhr
Perfekt für den Fall, dass Sie keinen Zugriff auf die RE-Bibliothek haben, wie z. B. bestimmte kleine Mikrocontroller. 🙂
– tudor -Monica wieder einsetzen-
1. Mai 2014 um 3:40 Uhr
Ich denke, das ist auch expliziter als RE, also ist es irgendwie Noob-freundlich. Manchmal braucht man keine allgemeine Lösung für alles
– Adam Hughes
24. Januar 2015 um 5:47 Uhr
Genial. Ich hatte eine .split() in einer Situation mit mehreren Eingaben und musste abfangen, wenn der Benutzer, ich, die Eingaben mit einem Leerzeichen und nicht mit einem Komma trennte. Ich wollte schon aufgeben und mit re umwandeln, aber Ihre .replace()-Lösung traf den Nagel auf den Kopf. Vielen Dank.
– JayJay123
6. Juli 2015 um 2:22 Uhr
Viel klarer als eine Regex. Außerdem habe ich keine Lust, ein ganzes Modul zu importieren, nur um eine einzelne, scheinbar einfache Operation auszuführen.
– Przemek D
13. Juni 2018 um 12:33 Uhr
Eric O Lebigot
So viele Antworten, aber ich kann keine Lösung finden, die das effizient macht Titel der Fragen buchstäblich verlangt (Aufteilung auf mehrere mögliche Trennzeichen – stattdessen werden viele Antworten auf alles aufgeteilt, was kein Wort ist, was anders ist). Hier ist also eine Antwort auf die Frage im Titel, die sich auf Pythons Standard und Effizienz stützt re Modul:
>>> import re # Will be splitting on: , <space> - ! ? :
>>> filter(None, re.split("[, \-!?:]+", "Hey, you - what are you doing here!?"))
['Hey', 'you', 'what', 'are', 'you', 'doing', 'here']
wo:
das […] Streichhölzer eines der darin aufgeführten Trennzeichen,
das \- im regulären Ausdruck soll hier die spezielle Interpretation von verhindern - als Zeichenbereichsanzeige (wie in A-Z),
das + überspringt einen oder mehr Trennzeichen (kann dank der filter()aber dies würde unnötigerweise leere Zeichenfolgen zwischen übereinstimmenden Einzelzeichen-Trennzeichen erzeugen), und
filter(None, …) entfernt die möglicherweise durch führende und nachfolgende Trennzeichen erzeugten leeren Zeichenfolgen (da leere Zeichenfolgen einen falschen booleschen Wert haben).
Dies re.split() genau “Splits mit mehreren Trennzeichen”, wie im Fragentitel gefordert.
Diese Lösung ist außerdem immun gegen die Probleme mit Nicht-ASCII-Zeichen in Wörtern, die in einigen anderen Lösungen zu finden sind (siehe den ersten Kommentar zur Antwort von ghostdog74).
Das re -Modul ist viel effizienter (in Bezug auf Geschwindigkeit und Prägnanz) als Python-Schleifen und -Tests “von Hand” durchzuführen!
“Ich kann keine Lösung finden, die effizient das tut, was der Titel der Fragen wörtlich verlangt” – die zweite Antwort, die vor 5 Jahren gepostet wurde: stackoverflow.com/a/1059601/2642204.
– BartoszKP
2. Dezember 2014 um 14:00 Uhr
Diese Antwort wird nicht an Trennzeichen geteilt (aus einer Reihe von mehreren Trennzeichen): Sie wird stattdessen an allem geteilt, was nicht alphanumerisch ist. Trotzdem stimme ich zu, dass die Absicht des ursprünglichen Posters wahrscheinlich darin besteht, nur die Wörter beizubehalten, anstatt einige Satzzeichen zu entfernen.
– Eric O. Lebigot
2. Dezember 2014 um 14:31 Uhr
EOL: Ich denke, diese Antwort teilt sich in mehrere Trennzeichen auf. Wenn Sie der Zeichenfolge nicht alphanumerische Zeichen hinzufügen, die nicht angegeben sind, z. B. Unterstriche, werden sie nicht wie erwartet geteilt.
– GravityWell
7. Dezember 2014 um 20:33 Uhr
@EOL: Ich habe gerade festgestellt, dass ich von Ihrem Kommentar “Diese Antwort wird nicht geteilt …” verwirrt war. Ich dachte, “dies” bezog sich auf Ihre re.split-Antwort, aber mir ist jetzt klar, dass Sie Gimels Antwort gemeint haben. Ich denke, DIESE Antwort (die Antwort, die ich kommentiere) ist die beste Antwort 🙂
– GravityWell
8. Dezember 2014 um 12:38 Uhr
Die Ironie hier ist der Grund, warum diese Antwort nicht die meisten Stimmen erhält … es gibt technisch korrekte Antworten und dann gibt es das, wonach der ursprüngliche Anforderer sucht (was sie meinen und nicht was sie sagen). Dies ist eine großartige Antwort und ich habe sie kopiert, wenn ich sie brauche. Und doch löst die am besten bewertete Antwort für mich ein Problem, das dem sehr ähnlich ist, woran der Poster gearbeitet hat, schnell, sauber und mit minimalem Code. Wenn eine einzige Antwort beide Lösungen gepostet hätte, hätte ich dafür 4 gestimmt. Welche 1 besser ist, hängt davon ab, was Sie tatsächlich versuchen zu tun (nicht die “How-To”-Quest, die gefragt wird). 🙂
– TMWP
21. März 2017 um 17:45 Uhr
Terry A
Ein anderer Weg, ohne Regex
import string
punc = string.punctuation
thestring = "Hey, you - what are you doing here!?"
s = list(thestring)
''.join([o for o in s if not o in punc]).split()
“Ich kann keine Lösung finden, die effizient das tut, was der Titel der Fragen wörtlich verlangt” – die zweite Antwort, die vor 5 Jahren gepostet wurde: stackoverflow.com/a/1059601/2642204.
– BartoszKP
2. Dezember 2014 um 14:00 Uhr
Diese Antwort wird nicht an Trennzeichen geteilt (aus einer Reihe von mehreren Trennzeichen): Sie wird stattdessen an allem geteilt, was nicht alphanumerisch ist. Trotzdem stimme ich zu, dass die Absicht des ursprünglichen Posters wahrscheinlich darin besteht, nur die Wörter beizubehalten, anstatt einige Satzzeichen zu entfernen.
– Eric O. Lebigot
2. Dezember 2014 um 14:31 Uhr
EOL: Ich denke, diese Antwort teilt sich in mehrere Trennzeichen auf. Wenn Sie der Zeichenfolge nicht alphanumerische Zeichen hinzufügen, die nicht angegeben sind, z. B. Unterstriche, werden sie nicht wie erwartet geteilt.
– GravityWell
7. Dezember 2014 um 20:33 Uhr
@EOL: Ich habe gerade festgestellt, dass ich von Ihrem Kommentar “Diese Antwort wird nicht geteilt …” verwirrt war. Ich dachte, “dies” bezog sich auf Ihre re.split-Antwort, aber mir ist jetzt klar, dass Sie Gimels Antwort gemeint haben. Ich denke, DIESE Antwort (die Antwort, die ich kommentiere) ist die beste Antwort 🙂
– GravityWell
8. Dezember 2014 um 12:38 Uhr
Die Ironie hier ist der Grund, warum diese Antwort nicht die meisten Stimmen erhält … es gibt technisch korrekte Antworten und dann gibt es das, wonach der ursprüngliche Anforderer sucht (was sie meinen und nicht was sie sagen). Dies ist eine großartige Antwort und ich habe sie kopiert, wenn ich sie brauche. Und doch löst die am besten bewertete Antwort für mich ein Problem, das dem sehr ähnlich ist, woran der Poster gearbeitet hat, schnell, sauber und mit minimalem Code. Wenn eine einzige Antwort beide Lösungen gepostet hätte, hätte ich dafür 4 gestimmt. Welche 1 besser ist, hängt davon ab, was Sie tatsächlich versuchen zu tun (nicht die “How-To”-Quest, die gefragt wird). 🙂
– TMWP
21. März 2017 um 17:45 Uhr
Jewgeni Sergejew
Pro-Tipp: Verwenden string.translate für die schnellsten Zeichenfolgenoperationen, die Python hat.
Einige Beweise …
Zuerst der langsame Weg (sorry pprzemek):
>>> import timeit
>>> S = 'Hey, you - what are you doing here!?'
>>> def my_split(s, seps):
... res = [s]
... for sep in seps:
... s, res = res, []
... for seq in s:
... res += seq.split(sep)
... return res
...
>>> timeit.Timer('my_split(S, punctuation)', 'from __main__ import S,my_split; from string import punctuation').timeit()
54.65477919578552
Als nächstes verwenden wir re.findall() (wie in der vorgeschlagenen Antwort angegeben). Viel schneller:
>>> timeit.Timer('findall(r"\w+", S)', 'from __main__ import S; from re import findall').timeit()
4.194725036621094
Schließlich verwenden wir translate:
>>> from string import translate,maketrans,punctuation
>>> T = maketrans(punctuation, ' '*len(punctuation))
>>> timeit.Timer('translate(S, T).split()', 'from __main__ import S,T,translate').timeit()
1.2835021018981934
Erläuterung:
string.translate ist in C implementiert und im Gegensatz zu vielen String-Manipulationsfunktionen in Python, string.translatenicht eine neue Saite erzeugen. Es ist also ungefähr so schnell, wie Sie für die Zeichenfolgensubstitution bekommen können.
Es ist jedoch etwas umständlich, da es eine Übersetzungstabelle benötigt, um diese Magie auszuführen. Sie können eine Übersetzungstabelle mit erstellen maketrans() Komfortfunktion. Das Ziel hier ist, alle unerwünschten Zeichen in Leerzeichen zu übersetzen. Ein Eins-zu-Eins-Ersatz. Auch hier werden keine neuen Daten erzeugt. Das ist also schnell!
Als nächstes verwenden wir das gute alte split(). split() arbeitet standardmäßig mit allen Leerzeichen und gruppiert sie für die Teilung. Das Ergebnis ist die Liste der gewünschten Wörter. Und dieser Ansatz ist fast 4x schneller als re.findall()!
Ich habe hier einen Test gemacht, und wenn Sie Unicode verwenden müssen, verwenden Sie patt = re.compile(ur'\w+', re.UNICODE); patt.findall(S) ist schneller als translate, da Sie die Zeichenfolge codieren müssen, bevor Sie die Transformation anwenden, und jedes Element in der Liste nach der Teilung decodieren müssen, um zu Unicode zurückzukehren.
– Rafael S. Calsaverini
15. Januar 2013 um 11:31 Uhr
Sie können die Übersetzungsimplementierung einzeilig machen und sicherstellen, dass S nicht zu den Splittern gehört, mit: s.translate(''.join([(chr(i) if chr(i) not in seps else seps[0]) for i in range(256)])).split(seps[0])
– Kochfelder
1. April 2014 um 22:56 Uhr
Keine genommen. Du vergleichst Äpfel und Birnen. 😉 Meine Lösung in Python 3 funktioniert immer noch ;P und unterstützt Trennzeichen mit mehreren Zeichen. 🙂 Versuchen Sie das auf einfache Weise, ohne einen neuen String zuzuweisen. 🙂 aber wahr, meins beschränkt sich auf das Analysieren von Befehlszeilenparametern und nicht zum Beispiel auf ein Buch.
– pprzemek
27. Oktober 2017 um 10:17 Uhr
Sie sagen “erzeugt keine neue Zeichenfolge”, was bedeutet, dass es an der angegebenen Zeichenfolge funktioniert? Ich habe es jetzt mit Python 2.7 getestet und es ändert die ursprüngliche Zeichenfolge nicht und gibt eine neue zurück.
– Prokop Hapala
15. September 2019 um 10:27 Uhr
string.translate und string.maketrans sind in Python 3 nicht verfügbar, sondern nur in Python 2.
– Futal
28. Oktober 2021 um 11:03 Uhr
11373900cookie-checkTeilen Sie Zeichenfolgen mit mehreren Wortbegrenzungszeichen in Wörter aufyes
docs.python.org/library/re.html
– mtasic85
29. Juni 2009 um 18:03 Uhr
Pythons
str.split()
funktioniert auch ganz ohne Argumente– Iwan Winogradow
8. Mai 2018 um 9:04 Uhr