In Python durch Komma und Leerzeichen trennen


346

Ich habe Python-Code, der durch Komma geteilt wird, aber das Leerzeichen nicht entfernt:

>>> string = "blah, lots  ,  of ,  spaces, here "
>>> mylist = string.split(',')
>>> print mylist
['blah', ' lots  ', '  of ', '  spaces', ' here ']

Ich würde lieber Leerzeichen wie folgt entfernen:

['blah', 'lots', 'of', 'spaces', 'here']

Ich bin mir bewusst, dass ich die Liste durchlaufen und jedes Element entfernen () kann, aber da dies Python ist, gibt es vermutlich eine schnellere, einfachere und elegantere Möglichkeit, dies zu tun.

Antworten:


594

Verwenden Sie das Listenverständnis - einfacher und genauso einfach zu lesen wie eine forSchleife.

my_string = "blah, lots  ,  of ,  spaces, here "
result = [x.strip() for x in my_string.split(',')]
# result is ["blah", "lots", "of", "spaces", "here"]

Siehe: Python-Dokumente zum Listenverständnis
Eine gute 2-Sekunden-Erklärung zum Listenverständnis.


1
Super gut! Ich habe ein Element wie folgt hinzugefügt, um die leeren Listeneinträge zu entfernen. > text = [x.strip () für x in text.split ('.') wenn x! = '']
RandallShanePhD

@ Sean: War ungültiger / unvollständiger Python-Code Ihre "ursprüngliche Absicht des Beitrags"? Laut den Review-Wichsern war es: stackoverflow.com/review/suggested-edits/21504253 . Können Sie ihnen bitte etwas anderes sagen, indem Sie die Korrektur vornehmen, wenn sie (erneut) falsch sind?
Futter

Das Original wurde von einem REPL Kopie kleistert (wenn ich mich richtig erinnere) , und das Ziel war das Verständnis des zugrunde liegenden Konzepts (mit Liste Verständnis , eine Operation auszuführen) - aber du hast recht, es macht mehr Sinn , wenn Sie sehen , dass die Liste Verständnis erzeugt eine neue Liste.
Sean Vieira

24

Mit einem regulären Ausdruck teilen. Hinweis: Ich habe den Fall mit führenden Leerzeichen allgemeiner gestaltet. Das Listenverständnis besteht darin, die Nullzeichenfolgen vorne und hinten zu entfernen.

>>> import re
>>> string = "  blah, lots  ,  of ,  spaces, here "
>>> pattern = re.compile("^\s+|\s*,\s*|\s+$")
>>> print([x for x in pattern.split(string) if x])
['blah', 'lots', 'of', 'spaces', 'here']

Dies funktioniert auch dann, wenn ^\s+es nicht übereinstimmt:

>>> string = "foo,   bar  "
>>> print([x for x in pattern.split(string) if x])
['foo', 'bar']
>>>

Hier ist, warum Sie ^ \ s + benötigen:

>>> pattern = re.compile("\s*,\s*|\s+$")
>>> print([x for x in pattern.split(string) if x])
['  blah', 'lots', 'of', 'spaces', 'here']

Sehen Sie die führenden Räume in bla?

Erläuterung: Oben wird der Python 3-Interpreter verwendet, die Ergebnisse in Python 2 sind jedoch dieselben.


8
Ich glaube, es [x.strip() for x in my_string.split(',')]ist pythonischer für die gestellte Frage. Vielleicht gibt es Fälle, in denen meine Lösung notwendig ist. Ich werde diesen Inhalt aktualisieren, wenn ich auf einen stoße.
TBC0

Warum ist ^\s+notwendig? Ich habe Ihren Code ohne ihn getestet und er funktioniert nicht, aber ich weiß nicht warum.
Laike9m

Wenn ich benutze re.compile("^\s*,\s*$"), ist das Ergebnis [' blah, lots , of , spaces, here '].
Laike9m

@ laike9m, ich habe meine Antwort aktualisiert, um Ihnen den Unterschied zu zeigen. ^\s+macht. Wie Sie selbst sehen können, werden ^\s*,\s*$auch die gewünschten Ergebnisse nicht zurückgegeben. Wenn Sie also mit einem regulären Ausdruck teilen möchten, verwenden Sie ^\s+|\s*,\s*|\s+$.
TBC0

Die erste Übereinstimmung ist leer, wenn das führende Muster (^ \ s +) nicht übereinstimmt, sodass Sie für die Zeichenfolge "foo, bar" so etwas wie ['', 'foo', 'bar'] erhalten.
Steeve McCauley

21

Ich kam, um hinzuzufügen:

map(str.strip, string.split(','))

aber sah, dass es bereits von Jason Orendorff in einem Kommentar erwähnt worden war .

Als ich Glenn Maynards Kommentar in derselben Antwort las, in der Listenverständnisse über die Karte vorgeschlagen wurden, begann ich mich zu fragen, warum. Ich nahm an, dass er aus Performancegründen meinte, aber natürlich könnte er aus stilistischen Gründen gemeint sein oder etwas anderes (Glenn?).

Ein schneller (möglicherweise fehlerhafter?) Test auf meiner Box, bei dem die drei Methoden in einer Schleife angewendet wurden, ergab:

[word.strip() for word in string.split(',')]
$ time ./list_comprehension.py 
real    0m22.876s

map(lambda s: s.strip(), string.split(','))
$ time ./map_with_lambda.py 
real    0m25.736s

map(str.strip, string.split(','))
$ time ./map_with_str.strip.py 
real    0m19.428s

machen map(str.strip, string.split(','))den Sieger, obwohl es scheint , sie sind alle in derselben Liga.

Natürlich sollte eine Karte (mit oder ohne Lambda) aus Leistungsgründen nicht unbedingt ausgeschlossen werden, und für mich ist sie mindestens so klar wie ein Listenverständnis.

Bearbeiten:

Python 2.6.5 unter Ubuntu 10.04


15

Entfernen Sie einfach den Leerraum aus der Zeichenfolge, bevor Sie ihn teilen.

mylist = my_string.replace(' ','').split(',')

10
Ein Problem, wenn die durch Kommas getrennten Elemente eingebettete Leerzeichen enthalten, z "you just, broke this".
Robert Rossney

1
Geeze, ein -1 dafür. Ihr seid hart. Es löste sein Problem, vorausgesetzt, seine Beispieldaten bestanden nur aus einzelnen Wörtern und es gab keine Spezifikation, dass die Daten Phrasen sein würden. Aber w / e, ich denke, so rollt ihr hier herum.
user489041

Na trotzdem danke, User. Um fair zu sein, habe ich speziell nach split gefragt und dann strip () und strip entfernt führende und nachfolgende Leerzeichen und berührt nichts dazwischen. Eine kleine Änderung und Ihre Antwort würden jedoch perfekt funktionieren: mylist = mystring.strip (). Split (','), obwohl ich nicht weiß, ob dies besonders effizient ist.
Mr_Chimp

12

Ich weiß, dass dies bereits beantwortet wurde, aber wenn Sie dies häufig beenden, sind reguläre Ausdrücke möglicherweise der bessere Weg:

>>> import re
>>> re.sub(r'\s', '', string).split(',')
['blah', 'lots', 'of', 'spaces', 'here']

Das \sentspricht jedem Leerzeichen, und wir ersetzen es einfach durch eine leere Zeichenfolge ''. Weitere Informationen finden Sie hier: http://docs.python.org/library/re.html#re.sub


3
Ihr Beispiel funktioniert nicht mit Zeichenfolgen, die Leerzeichen enthalten. "zum Beispiel dies, eins" würde "für", "beispielhaft", "eins" werden. Ohne zu sagen, dass es eine schlechte Lösung ist (es funktioniert perfekt in meinem Beispiel), hängt es nur von der jeweiligen Aufgabe ab!
Mr_Chimp

Ja, das ist sehr richtig! Sie könnten wahrscheinlich den regulären Ausdruck so anpassen, dass er Zeichenfolgen mit Leerzeichen verarbeiten kann, aber wenn das Listenverständnis funktioniert, würde ich sagen, bleiben Sie dabei;)
Brad Montgomery

2
import re
result=[x for x in re.split(',| ',your_string) if x!='']

Das funktioniert gut für mich.


2

re (wie in regulären Ausdrücken) ermöglicht das Aufteilen auf mehrere Zeichen gleichzeitig:

$ string = "blah, lots  ,  of ,  spaces, here "
$ re.split(', ',string)
['blah', 'lots  ', ' of ', ' spaces', 'here ']

Dies funktioniert nicht gut für Ihre Beispielzeichenfolge, aber gut für eine durch Kommas getrennte Liste. Für Ihre Beispielzeichenfolge können Sie die re.split-Leistung kombinieren, um Regex-Muster zu teilen , um einen "Split-on-this-or-that" -Effekt zu erzielen.

$ re.split('[, ]',string)
['blah',
 '',
 'lots',
 '',
 '',
 '',
 '',
 'of',
 '',
 '',
 '',
 'spaces',
 '',
 'here',
 '']

Leider ist das hässlich, aber ein filterWille macht den Trick:

$ filter(None, re.split('[, ]',string))
['blah', 'lots', 'of', 'spaces', 'here']

Voila!


2
Warum nicht einfach re.split(' *, *', string)?
Paul Tomblin

4
@ PaulTomblin gute Idee. Man kann dies auch getan haben: re.split('[, ]*',string)für den gleichen Effekt.
Dannid

Dannid wurde mir nach dem Schreiben klar, dass es am Anfang und am Ende keine Leerzeichen entfernt, wie es die Antwort von @ tbc0 tut.
Paul Tomblin

@PaulTomblinheh, und meine Gegenargumentation [, ]*hinterlässt am Ende der Liste eine leere Zeichenfolge. Ich denke, Filter ist immer noch eine nette Sache, um sie dort hineinzuwerfen oder sich an das Listenverständnis zu halten, wie es die Top-Antwort tut.
Dannid

1

map(lambda s: s.strip(), mylist)wäre ein bisschen besser als explizite Schleifen. Oder für das Ganze auf einmal:map(lambda s:s.strip(), string.split(','))


10
Tipp: Überprüfen mapSie jedes Mal , wenn Sie es verwenden , insbesondere wenn Sie lambdaes verwenden, noch einmal, ob Sie ein Listenverständnis verwenden sollten.
Glenn Maynard

11
Sie können das Lambda mit vermeiden map(str.strip, s.split(',')).
Jason Orendorff


1
import re
mylist = [x for x in re.compile('\s*[,|\s+]\s*').split(string)]

Einfach Komma oder mindestens ein Leerzeichen mit / ohne vorhergehende / nachfolgende Leerzeichen.

Bitte versuche!


0

map(lambda s: s.strip(), mylist)wäre ein bisschen besser als explizite Schleifen.
Oder für das Ganze auf einmal:

map(lambda s:s.strip(), string.split(','))

Das ist im Grunde alles was Sie brauchen.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.