@Ivo, keine dieser Aussagen ist wahr. Sie sollten niemals eine Liste ändern, über die for x in listSie iterieren. Wenn Sie eine verwenden, while loopist dies in Ordnung. Die gezeigte Schleife entfernt leere Zeichenfolgen, bis keine leeren Zeichenfolgen mehr vorhanden sind, und stoppt dann. Ich hatte mir die Frage (nur den Titel) nicht einmal angesehen, aber ich antwortete mit genau der gleichen Schleife wie möglich! Wenn Sie aus Gründen des Gedächtnisses keine Verständnisse oder Filter verwenden möchten, ist dies eine sehr pythonische Lösung.
Aaronasterling
4
Immer noch ein sehr gültiger Punkt, um die Liste, über die Sie iterieren, niemals zu ändern :)
Eduard Luca
1
@EduardLuca Wenn der Zweck des Durchlaufens einer Liste darin besteht, sie zu ändern, ist dies das Gegenteil von dem, was Sie tun sollten. Sie müssen nur darauf achten, dass Sie wissen, dass Sie dadurch kein unerwartetes Verhalten verursachen.
JFA
1
@EduardLuca, @JFA: Der Punkt ist, dass er KEINE Liste durchläuft. Er würde, wenn er etwas in der Form geschrieben hätte for var in list:, aber hier hat er geschrieben while const in list:. was nicht über irgendetwas iteriert. Es wird nur derselbe Code wiederholt, bis eine Bedingung falsch ist.
Wenn Sie , dass für die Leistung gedrückt, itertool‚sifilter ist auch faster- >>> timeit('filter(None, str_list)', 'str_list=["a"]*1000', number=100000)2.3468542098999023; >>> timeit('itertools.ifilter(None, str_list)', 'str_list=["a"]*1000', number=100000)0.04442191123962402.
Humphrey Bogart
4
@cpburnz Sehr wahr. Die ifilterErgebnisse werden jedoch träge und nicht auf einmal ausgewertet - ich würde argumentieren, dass dies in den meisten Fällen ifilterbesser ist. Interessant, dass die Verwendung filterimmer noch schneller ist als das Einwickeln eines ifilterIn list.
Humphrey Bogart
3
Wenn Sie dies mit einer Liste von Zahlen tun, beachten Sie, dass auch Nullen entfernt werden (Hinweis: Ich habe nur die ersten drei Methoden verwendet), sodass Sie eine alternative Methode benötigen.
Schnarchen Frosch
2
Dies konzentriert sich nur auf die Geschwindigkeit, nicht darauf, wie pythonisch die Lösung ist (die Frage, die gestellt wurde). Listenverständnisse sind die pythonische Lösung, und Filter sollten nur verwendet werden, wenn die Profilerstellung bewiesen hat, dass der Listencomp ein Engpass ist.
Tritium21
3
@ wer-erwähnt-über-oder-impliziert-Python-3, bitte bearbeiten und aktualisieren Sie einfach die Antwort. Wir haben nur für Python 2 diskutiert, als diese Frage gestellt wurde, sogar Python 3 wurde fast 2 Jahre veröffentlicht. Aktualisieren Sie jedoch die Ergebnisse von Python 2 und 3.
Ich mag diese Lösung, weil sie leicht anpassbar ist. Wenn ich nicht nur leere Zeichenfolgen entfernen müsste, sondern auch Zeichenfolgen, die nur Leerzeichen sind, zum Beispiel : [x for x in strings if x.strip()].
Bond
67
Filter hat tatsächlich eine spezielle Option dafür:
filter(None, sequence)
Es werden alle Elemente herausgefiltert, die als falsch ausgewertet werden. Hier muss kein tatsächlicher Callable wie bool, len usw. verwendet werden.
Dies ist in der Tat eine Python-Sprache. Es ist auch das einzige Mal, dass ich filter () noch benutze, Listenverständnisse haben überall sonst übernommen.
Beachten Sie, dass filter(None, lstr)leere Zeichenfolgen nicht mit einem Leerzeichen entfernt werden ' ', sondern nur entfernt werden, ''während ' '.join(lstr).split()beide entfernt werden.
Die Verwendung filter()mit entfernten Leerzeichenstrings dauert viel länger:
>>> timeit('filter(None, [l.replace(" ", "") for l in lstr])',"lstr=['hello', '', ' ', 'world', ' ']", number=10000000)18.101892948150635
Es funktioniert nicht, wenn Sie Platz in der Zeichenfolge eines Wortes haben. Zum Beispiel: ['Hallo Welt', '', 'Hallo', '']. >> ['helloworld', '', 'hallo', ''] Haben Sie eine andere Lösung, um Leerzeichen innerhalb eines Elements in der Liste beizubehalten, aber andere zu entfernen?
Reihan_amn
Beachten Sie, dass filter(None, lstr)leere Zeichenfolgen nicht mit einem Leerzeichen entfernt werden.' ' Ja, da dies keine leere Zeichenfolge ist.
AMC
15
Die Antwort von @ Ib33X ist fantastisch. Wenn Sie jede leere Zeichenfolge nach dem Entfernen entfernen möchten. Sie müssen auch die Strip-Methode verwenden. Andernfalls wird auch die leere Zeichenfolge zurückgegeben, wenn Leerzeichen vorhanden sind. Wie "" gilt auch für diese Antwort. So kann erreicht werden durch.
strings =["first","","second "," "][x.strip()for x in strings if x.strip()]
Die Antwort darauf wird sein ["first", "second"].
Wenn Sie filterstattdessen die Methode verwenden möchten , können Sie dies tun
list(filter(lambda item: item.strip(), strings)). Dies ergibt das gleiche Ergebnis.
Wenn Ihre Listen unterschiedliche Typen haben (außer Keine), liegt möglicherweise ein größeres Problem vor.
Tritium21
Welche Arten? Ich habe es mit int und anderen numerischen Typen, Strings, Listen, Tupes, Sets und None versucht und dort keine Probleme. Ich konnte sehen, dass wenn es benutzerdefinierte Typen gibt, die die str-Methode nicht unterstützen, dies ein Problem darstellen könnte. Sollte ich mir Sorgen um andere machen?
Thiruvenkadam
1
Wenn Sie eine haben str_list = [None, '', 0, "Hi", '', "Hello"], ist dies ein Zeichen für eine schlecht gestaltete Anwendung. Sie sollten nicht mehr als eine Schnittstelle (Typ) und Keine in derselben Liste haben.
Tritium21
3
Daten von db abrufen? Liste der Argumente für eine Funktion beim automatisierten Testen?
Thiruvenkadam
3
Das sind normalerweise Tupel.
Tritium21
7
Abhängig von der Größe Ihrer Liste ist es möglicherweise am effizientesten, wenn Sie list.remove () verwenden, anstatt eine neue Liste zu erstellen:
l =["1","","3",""]whileTrue:try:
l.remove("")exceptValueError:break
Dies hat den Vorteil, dass keine neue Liste erstellt wird, aber den Nachteil, dass jedes Mal von Anfang an gesucht werden muss, obwohl im Gegensatz while '' in lzur oben vorgeschlagenen Verwendung nur einmal pro Auftreten von gesucht werden muss ''(es gibt sicherlich eine Möglichkeit, das Beste zu behalten beide Methoden, aber es ist komplizierter).
Sie können die Liste an Ort und Stelle bearbeiten ary[:] = [e for e in ary if e]. Viel sauberer und verwendet keine Ausnahmen für den Kontrollfluss.
Krzysztof Karski
2
Nun, das ist nicht wirklich "an Ort und Stelle" - ich bin mir ziemlich sicher, dass dies eine neue Liste erstellt und sie einfach dem Namen des alten zuweist.
Andrew Jaffe
Dies funktioniert sehr schlecht, da das Ende der Daten bei jeder Entfernung im Speicher herumgemischt wird. Besser alles mit einem Schlag entfernen.
wim
7
Beachten Sie, dass Sie die Leerzeichen in einer Zeichenfolge möglicherweise unbeabsichtigt entfernen, indem Sie einige Ansätze verwenden. Wenn Sie diese Liste haben
['Hallo Welt', '', '', 'Hallo'] was du willst ['Hallo Welt', 'Hallo']
Schneiden Sie zuerst die Liste, um eine beliebige Art von Leerzeichen in eine leere Zeichenfolge umzuwandeln:
space_to_empty =[x.strip()for x in _text_list]
Entfernen Sie dann die leere Zeichenfolge aus der Liste
space_clean_list =[x for x in space_to_empty if x]
Wenn Sie die Leerzeichen innerhalb einer Zeichenfolge behalten möchten, können Sie sie mithilfe einiger Ansätze unbeabsichtigt entfernen. Wie dieser Ansatz dann?
AMC
Danke Alter, es hat bei mir mit einer kleinen Veränderung funktioniert. dhspace_clean_list = [x.strip() for x in y if x.strip()]
Muhammad Mehran Khan Attari
6
Verwendung filter:
newlist=filter(lambda x: len(x)>0, oldlist)
Die Nachteile der Verwendung von Filtern bestehen darin, dass sie langsamer als Alternativen sind. Auch lambdaist in der Regel teuer.
Oder Sie können sich für das einfachste und iterativste von allen entscheiden:
# I am assuming listtext is the original list containing (possibly) empty itemsfor item in listtext:if item:
newlist.append(str(item))# You can remove str() based on the content of your original list
Dies ist die intuitivste der Methoden und wird in angemessener Zeit durchgeführt.
Willkommen bei SO. Sie wurden nicht ignoriert. Sie wurden nicht von einem nicht alltäglichen Downvoter angegriffen. Sie haben Feedback erhalten. Verstärkung: Ihr vorgeschlagenes erstes Argument für Filter ist schlechter als lambda x: len(x)das schlechtere als lambda x : xdas schlechteste der 4 Lösungen in der ausgewählten Antwort. Eine korrekte Funktion ist bevorzugt, aber nicht ausreichend. Bewegen Sie den Mauszeiger über die Downvote-Schaltfläche: "Diese Antwort ist nicht nützlich".
John Machin
5
Wie von Aziz Alto berichtet filter(None, lstr), werden leere Zeichenfolgen nicht mit einem Leerzeichen entfernt. ' 'Wenn Sie jedoch sicher sind, dass lstr nur Zeichenfolgen enthält, können Sie diese verwendenfilter(str.strip, lstr)
Sie können sehen, dass filter(str.strip, lstr)Zeichenfolgen mit Leerzeichen beibehalten ' '.join(lstr).split()werden, diese Zeichenfolgen jedoch aufgeteilt werden.
Dies funktioniert nur, wenn Ihre Zeichenfolgen keine Leerzeichen enthalten. Andernfalls teilen Sie diese Zeichenfolgen ebenfalls auf.
Phillyslick
1
@BenPolinsky, wie Sie die joinLösung gemeldet haben, teilt Zeichenfolgen mit Leerzeichen, Filter jedoch nicht. Vielen Dank für Ihren Kommentar. Ich habe meine Antwort verbessert.
Paolo Melchiorre
-1
Fassen Sie die besten Antworten zusammen:
1. Beseitigen Sie Leergut OHNE Abisolieren:
Das heißt, All-Space-Zeichenfolgen bleiben erhalten:
slist = list(filter(None, slist))
PROs:
am einfachsten;
am schnellsten (siehe Benchmarks unten).
2. Um Leergut nach dem Abisolieren zu beseitigen ...
2.a ... wenn Zeichenfolgen KEINE Leerzeichen zwischen Wörtern enthalten:
slist =' '.join(slist).split()
PROs:
kleiner Code
schnell (ABER nicht am schnellsten bei großen Datenmengen aufgrund des Speichers, im Gegensatz zu den Ergebnissen von @ paolo-melchiorre)
2.b ... wenn Strings Leerzeichen zwischen Wörtern enthalten?
slist = list(filter(str.strip, slist))
PROs:
am schnellsten;
Verständlichkeit des Codes.
Benchmarks auf einer Maschine von 2018:
## Build test-data#import random, string
nwords =10000
maxlen =30
null_ratio =0.1
rnd = random.Random(0)# deterministic results
words =[' '* rnd.randint(0, maxlen)if rnd.random()>(1- null_ratio)else''.join(random.choices(string.ascii_letters, k=rnd.randint(0, maxlen)))for _i in range(nwords)]## Test functions#def nostrip_filter(slist):return list(filter(None, slist))def nostrip_comprehension(slist):return[s for s in slist if s]def strip_filter(slist):return list(filter(str.strip, slist))def strip_filter_map(slist):return list(filter(None, map(str.strip, slist)))def strip_filter_comprehension(slist):# waste memoryreturn list(filter(None,[s.strip()for s in slist]))def strip_filter_generator(slist):return list(filter(None,(s.strip()for s in slist)))def strip_join_split(slist):# words without(!) spacesreturn' '.join(slist).split()## Benchmarks#%timeit nostrip_filter(words)142µs ±16.8µs per loop (mean ± std. dev. of 7 runs,10000 loops each)%timeit nostrip_comprehension(words)263µs ±19.1µs per loop (mean ± std. dev. of 7 runs,1000 loops each)%timeit strip_filter(words)653µs ±37.5µs per loop (mean ± std. dev. of 7 runs,1000 loops each)%timeit strip_filter_map(words)642µs ±36µs per loop (mean ± std. dev. of 7 runs,1000 loops each)%timeit strip_filter_comprehension(words)693µs ±42.2µs per loop (mean ± std. dev. of 7 runs,1000 loops each)%timeit strip_filter_generator(words)750µs ±28.6µs per loop (mean ± std. dev. of 7 runs,1000 loops each)%timeit strip_join_split(words)796µs ±103µs per loop (mean ± std. dev. of 7 runs,1000 loops each)
s and s.strip()kann einfach vereinfacht werden s.strip().
AMC
s and s.strip()wird benötigt, wenn wir filter(None, words)die akzeptierte Antwort vollständig replizieren wollen . Ich habe oben x2 Beispielfunktionen korrigiert und x2 schlechte Funktionen gelöscht.
Ankostis
-2
Verwenden Sie für eine Liste mit einer Kombination aus Leerzeichen und leeren Werten das einfache Listenverständnis -
>>> s =['I','am','a','','great',' ','',' ','person','!!','Do','you','think','its','a','','a','','joke','',' ','','?','','','','?']
Sie sehen also, diese Liste enthält eine Kombination aus Leerzeichen und Nullelementen. Verwenden des Snippets -
>>> d =[x for x in s if x.strip()]>>> d
>>> d =['I','am','a','great','person','!!','Do','you','think','its','a','a','joke','?','?']
for x in list
Sie iterieren. Wenn Sie eine verwenden,while loop
ist dies in Ordnung. Die gezeigte Schleife entfernt leere Zeichenfolgen, bis keine leeren Zeichenfolgen mehr vorhanden sind, und stoppt dann. Ich hatte mir die Frage (nur den Titel) nicht einmal angesehen, aber ich antwortete mit genau der gleichen Schleife wie möglich! Wenn Sie aus Gründen des Gedächtnisses keine Verständnisse oder Filter verwenden möchten, ist dies eine sehr pythonische Lösung.for var in list:
, aber hier hat er geschriebenwhile const in list:
. was nicht über irgendetwas iteriert. Es wird nur derselbe Code wiederholt, bis eine Bedingung falsch ist.Antworten:
Ich würde verwenden
filter
:Python 3 gibt einen Iterator von zurück
filter
und sollte daher in einen Aufruf von eingeschlossen werdenlist()
quelle
itertool
‚sifilter
ist auch faster->>> timeit('filter(None, str_list)', 'str_list=["a"]*1000', number=100000)
2.3468542098999023
;>>> timeit('itertools.ifilter(None, str_list)', 'str_list=["a"]*1000', number=100000)
0.04442191123962402
.ifilter
Ergebnisse werden jedoch träge und nicht auf einmal ausgewertet - ich würde argumentieren, dass dies in den meisten Fällenifilter
besser ist. Interessant, dass die Verwendungfilter
immer noch schneller ist als das Einwickeln einesifilter
Inlist
.Die Verwendung eines Listenverständnisses ist der pythonischste Weg:
Wenn die Liste direkt geändert werden muss, da andere Referenzen die aktualisierten Daten enthalten müssen, verwenden Sie eine Slice-Zuweisung:
quelle
[x for x in strings if x.strip()]
.Filter hat tatsächlich eine spezielle Option dafür:
Es werden alle Elemente herausgefiltert, die als falsch ausgewertet werden. Hier muss kein tatsächlicher Callable wie bool, len usw. verwendet werden.
Es ist genauso schnell wie eine Karte (bool, ...)
quelle
Zeit vergleichen
Beachten Sie, dass
filter(None, lstr)
leere Zeichenfolgen nicht mit einem Leerzeichen entfernt werden' '
, sondern nur entfernt werden,''
während' '.join(lstr).split()
beide entfernt werden.Die Verwendung
filter()
mit entfernten Leerzeichenstrings dauert viel länger:quelle
filter(None, lstr)
leere Zeichenfolgen nicht mit einem Leerzeichen entfernt werden.' '
Ja, da dies keine leere Zeichenfolge ist.Die Antwort von @ Ib33X ist fantastisch. Wenn Sie jede leere Zeichenfolge nach dem Entfernen entfernen möchten. Sie müssen auch die Strip-Methode verwenden. Andernfalls wird auch die leere Zeichenfolge zurückgegeben, wenn Leerzeichen vorhanden sind. Wie "" gilt auch für diese Antwort. So kann erreicht werden durch.
Die Antwort darauf wird sein
["first", "second"]
.Wenn Sie
filter
stattdessen die Methode verwenden möchten , können Sie dies tunlist(filter(lambda item: item.strip(), strings))
. Dies ergibt das gleiche Ergebnis.quelle
Anstelle von if x würde ich if X! = '' Verwenden, um nur leere Zeichenfolgen zu entfernen. So was:
Dadurch bleibt der Datentyp "Keine" in Ihrer Liste erhalten. Falls Ihre Liste Ganzzahlen enthält und 0 eine davon ist, bleibt sie ebenfalls erhalten.
Zum Beispiel,
quelle
str_list = [None, '', 0, "Hi", '', "Hello"]
, ist dies ein Zeichen für eine schlecht gestaltete Anwendung. Sie sollten nicht mehr als eine Schnittstelle (Typ) und Keine in derselben Liste haben.Abhängig von der Größe Ihrer Liste ist es möglicherweise am effizientesten, wenn Sie list.remove () verwenden, anstatt eine neue Liste zu erstellen:
Dies hat den Vorteil, dass keine neue Liste erstellt wird, aber den Nachteil, dass jedes Mal von Anfang an gesucht werden muss, obwohl im Gegensatz
while '' in l
zur oben vorgeschlagenen Verwendung nur einmal pro Auftreten von gesucht werden muss''
(es gibt sicherlich eine Möglichkeit, das Beste zu behalten beide Methoden, aber es ist komplizierter).quelle
ary[:] = [e for e in ary if e]
. Viel sauberer und verwendet keine Ausnahmen für den Kontrollfluss.Beachten Sie, dass Sie die Leerzeichen in einer Zeichenfolge möglicherweise unbeabsichtigt entfernen, indem Sie einige Ansätze verwenden. Wenn Sie diese Liste haben
['Hallo Welt', '', '', 'Hallo'] was du willst ['Hallo Welt', 'Hallo']
Schneiden Sie zuerst die Liste, um eine beliebige Art von Leerzeichen in eine leere Zeichenfolge umzuwandeln:
Entfernen Sie dann die leere Zeichenfolge aus der Liste
quelle
space_clean_list = [x.strip() for x in y if x.strip()]
Verwendung
filter
:Die Nachteile der Verwendung von Filtern bestehen darin, dass sie langsamer als Alternativen sind. Auch
lambda
ist in der Regel teuer.Oder Sie können sich für das einfachste und iterativste von allen entscheiden:
Dies ist die intuitivste der Methoden und wird in angemessener Zeit durchgeführt.
quelle
lambda x: len(x)
das schlechtere alslambda x : x
das schlechteste der 4 Lösungen in der ausgewählten Antwort. Eine korrekte Funktion ist bevorzugt, aber nicht ausreichend. Bewegen Sie den Mauszeiger über die Downvote-Schaltfläche: "Diese Antwort ist nicht nützlich".Wie von Aziz Alto berichtet
filter(None, lstr)
, werden leere Zeichenfolgen nicht mit einem Leerzeichen entfernt.' '
Wenn Sie jedoch sicher sind, dass lstr nur Zeichenfolgen enthält, können Sie diese verwendenfilter(str.strip, lstr)
Vergleiche die Zeit auf meinem PC
Die schnellste Lösung zum Entfernen
''
und Leeren von Zeichenfolgen mit einem Leerzeichen' '
bleibt bestehen' '.join(lstr).split()
.Wie in einem Kommentar berichtet, ist die Situation anders, wenn Ihre Zeichenfolgen Leerzeichen enthalten.
Sie können sehen, dass
filter(str.strip, lstr)
Zeichenfolgen mit Leerzeichen beibehalten' '.join(lstr).split()
werden, diese Zeichenfolgen jedoch aufgeteilt werden.quelle
join
Lösung gemeldet haben, teilt Zeichenfolgen mit Leerzeichen, Filter jedoch nicht. Vielen Dank für Ihren Kommentar. Ich habe meine Antwort verbessert.Fassen Sie die besten Antworten zusammen:
1. Beseitigen Sie Leergut OHNE Abisolieren:
Das heißt, All-Space-Zeichenfolgen bleiben erhalten:
PROs:
2. Um Leergut nach dem Abisolieren zu beseitigen ...
2.a ... wenn Zeichenfolgen KEINE Leerzeichen zwischen Wörtern enthalten:
PROs:
2.b ... wenn Strings Leerzeichen zwischen Wörtern enthalten?
PROs:
Benchmarks auf einer Maschine von 2018:
quelle
s and s.strip()
kann einfach vereinfacht werdens.strip()
.s and s.strip()
wird benötigt, wenn wirfilter(None, words)
die akzeptierte Antwort vollständig replizieren wollen . Ich habe oben x2 Beispielfunktionen korrigiert und x2 schlechte Funktionen gelöscht.Verwenden Sie für eine Liste mit einer Kombination aus Leerzeichen und leeren Werten das einfache Listenverständnis -
Sie sehen also, diese Liste enthält eine Kombination aus Leerzeichen und Nullelementen. Verwenden des Snippets -
quelle