Ich möchte alle leeren Zeichenfolgen aus einer Liste von Zeichenfolgen in Python entfernen.
Meine Idee sieht so aus:
while '' in str_list:
str_list.remove('')
Gibt es einen pythonischeren Weg, dies zu tun?
nulldx
Ich möchte alle leeren Zeichenfolgen aus einer Liste von Zeichenfolgen in Python entfernen.
Meine Idee sieht so aus:
while '' in str_list:
str_list.remove('')
Gibt es einen pythonischeren Weg, dies zu tun?
besser leben
ich würde … benutzen filter
:
str_list = filter(None, str_list)
str_list = filter(bool, str_list)
str_list = filter(len, str_list)
str_list = filter(lambda item: item, str_list)
Python 3 gibt einen Iterator von zurück filter
sollte also in einen Aufruf von eingeschlossen werden list()
str_list = list(filter(None, str_list))
Wenn du bist das Leistungsdruck, itertool
‘s ifilter
ist noch schneller—>>> 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
21. Juli 2011 um 11:02 Uhr
@cpburnz Sehr wahr. Allerdings mit ifilter
Ergebnisse werden träge ausgewertet, nicht auf einmal – das würde ich für die meisten Fälle behaupten ifilter
ist besser. Interessant, dass mit filter
ist immer noch schneller als ein Wickeln ifilter
in einem list
obwohl.
– Humphrey Bogart
14. September 2012 um 11:03 Uhr
Wenn Sie dies mit einer Liste von Zahlen tun, beachten Sie, dass auch Nullen entfernt werden (Hinweis: Ich habe nur die ersten 3 Methoden verwendet), sodass Sie eine alternative Methode benötigen.
– SnoringFrog
22. April 2014 um 6:29 Uhr
Dies konzentriert sich nur auf die Geschwindigkeit, nicht darauf, wie pythonisch die Lösung ist (die Frage, die gestellt wurde). List Comprehensions sind die pythonische Lösung, und Filter sollten nur verwendet werden, wenn die Profilerstellung bewiesen hat, dass listcomp ein Engpass ist.
– Tritium21
21. Februar 2015 um 18:18 Uhr
@whoever-mentions-about-or-imply-Python-3, bitte bearbeiten und aktualisieren Sie einfach die Antwort. Wir haben nur für Python 2 diskutiert, als diese Frage gestellt wurde, selbst Python 3 wurde vor fast 2 Jahren veröffentlicht. Aktualisieren Sie jedoch die Ergebnisse von Python 2 und 3.
– besser leben
29. März 2016 um 22:22 Uhr
Ib33X
Verwendung einer Listenverständnis ist der pythonischste Weg:
>>> strings = ["first", "", "second"]
>>> [x for x in strings if x]
['first', 'second']
Wenn die Liste direkt geändert werden muss, weil es andere Referenzen gibt, die die aktualisierten Daten sehen müssen, verwenden Sie eine Slice-Zuweisung:
strings[:] = [x for x in strings if x]
Ich mag diese Lösung, weil sie leicht anpassbar ist. Wenn ich nicht nur leere Zeichenfolgen entfernen musste, sondern Zeichenfolgen, die nur Leerzeichen sind, zum Beispiel: [x for x in strings if x.strip()]
.
– Bindung
29. Dezember 2015 um 16:28 Uhr
[x for x in strings if x] Das funktioniert gut, aber bitte erklären Sie, wie diese Schleife funktioniert?
– Amar Kumar
31. Januar 2021 um 17:08 Uhr
@AmarKumar In Python werden leere Zeichenfolgen als falsch ausgewertet, wenn sie in einem booleschen Kontext wie in angekündigt werden if x
. Die Klammern, for
Schleife und if
Klausel kombinieren zu lesen “Erzeuge eine Liste, die besteht aus x
für jedes Element in strings
wenn x
enthält tatsächlich etwas.” @ Ib33x Absolut tolle Arbeit. Diese Antwort ist sicherlich die pythonischste.
– Nat Rätsel
22. Februar 2021 um 21:37 Uhr
Nett. [x for x in strings if x.strip()]
Zeichenfolgen von Leerzeichen zu entfernen.
– PatrickT
2. August um 9:20 Uhr
Ivo van der Wijk
Filter hat dafür tatsächlich eine spezielle Option:
filter(None, sequence)
Es filtert alle Elemente heraus, die mit False ausgewertet werden. Es ist nicht erforderlich, hier ein tatsächlich aufrufbares Element wie bool, len usw. zu verwenden.
Es ist genauso schnell wie map(bool, …)
Dies ist tatsächlich ein Python-Idiom. Es ist auch das einzige Mal, dass ich filter() noch verwende, Listenverständnisse haben überall sonst übernommen.
– kaleisin
18. Februar 2014 um 8:24 Uhr
Ich finde es einfacher, die Absicht des Codes zu erkennen, verglichen mit einer Listenkomposition
– Martin CR
17. Dezember 2020 um 13:10 Uhr
Aziz Alto
>>> lstr = ['hello', '', ' ', 'world', ' ']
>>> lstr
['hello', '', ' ', 'world', ' ']
>>> ' '.join(lstr).split()
['hello', 'world']
>>> filter(None, lstr)
['hello', ' ', 'world', ' ']
Zeit vergleichen
>>> from timeit import timeit
>>> timeit('" ".join(lstr).split()', "lstr=['hello', '', ' ', 'world', ' ']", number=10000000)
4.226747989654541
>>> timeit('filter(None, lstr)', "lstr=['hello', '', ' ', 'world', ' ']", number=10000000)
3.0278358459472656
Beachte das filter(None, lstr)
entfernt keine leeren Zeichenfolgen mit einem Leerzeichen ' '
es schneidet nur weg ''
während ' '.join(lstr).split()
entfernt beides.
Benutzen filter()
Wenn Leerzeichen entfernt sind, dauert es viel länger:
>>> timeit('filter(None, [l.replace(" ", "") for l in lstr])', "lstr=['hello', '', ' ', 'world', ' ']", number=10000000)
18.101892948150635
ssi-anik
Die Antwort von @Ib33X ist großartig. Wenn Sie jede leere Zeichenfolge entfernen möchten, nachdem Sie sie entfernt haben. Sie müssen auch die Streifenmethode verwenden. Andernfalls wird auch der leere String zurückgegeben, wenn er Leerzeichen enthält. ” ” wird auch für diese Antwort gültig sein. 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 verwenden möchten filter
Methode stattdessen können Sie wie tun
list(filter(lambda item: item.strip(), strings))
. Dies ergibt das gleiche Ergebnis.
Können Sie dieses Stück erklären? Normalerweise gibt x.strip() False zurück, wir haben das Ergebnis, aber wie dieser Code funktioniert, habe ich die Logik nicht verstanden.
– Fuad Ak
17. Juni um 7:13
Das heißt, Zeichenfolgen, die nur aus Leerzeichen bestehen, werden beibehalten:
slist = list(filter(None, slist))
PROs:
slist=" ".join(slist).split()
PROs:
slist = list(filter(str.strip, slist))
PROs:
## 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 memory
return 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(!) spaces
return ' '.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)
Können Sie dieses Stück erklären? Normalerweise gibt x.strip() False zurück, wir haben das Ergebnis, aber wie dieser Code funktioniert, habe ich die Logik nicht verstanden.
– Fuad Ak
17. Juni um 7:13
thiruvenkadam
Anstelle von if x würde ich if X != ” verwenden, um nur leere Zeichenfolgen zu eliminieren. So was:
str_list = [x for x in str_list if x != '']
Dadurch wird der Datentyp None in Ihrer Liste beibehalten. Falls Ihre Liste ganze Zahlen enthält und 0 eine davon ist, wird sie ebenfalls beibehalten.
Zum Beispiel,
str_list = [None, '', 0, "Hi", '', "Hello"]
[x for x in str_list if x != '']
[None, 0, "Hi", "Hello"]
Wenn Ihre Listen unterschiedliche Typen haben (außer None), haben Sie möglicherweise ein größeres Problem.
– Tritium21
21. Februar 2015 um 18:14 Uhr
Welche Arten? Ich habe es mit int und anderen numerischen Typen, Strings, Listen, Tupes, Sets und None versucht und es gab keine Probleme. Ich konnte sehen, dass es ein Problem geben könnte, wenn es benutzerdefinierte Typen gibt, die die str-Methode nicht unterstützen. Muss ich mir um andere Sorgen machen?
– Thiruvenkadam
23. Februar 2015 um 6:53 Uhr
Wenn Sie eine haben str_list = [None, '', 0, "Hi", '', "Hello"]
, ist dies ein Zeichen für eine schlecht gestaltete Anwendung. Du sollte nicht haben mehr als eine Schnittstelle (Typ) und Keine in derselben Liste.
– Tritium21
23. Februar 2015 um 16:21 Uhr
Daten von db abrufen? Liste der Argumente für eine Funktion beim automatisierten Testen?
– Thiruvenkadam
24. Februar 2015 um 5:22 Uhr
Das sind normalerweise Tupel.
– Tritium21
24. Februar 2015 um 10:47 Uhr
@Ivo, keine dieser Aussagen ist wahr. Sie sollten niemals eine Liste ändern, die Sie beim Iterieren verwenden
for x in list
Wenn Sie eine verwendenwhile loop
dann ist es in Ordnung. Die gezeigte Schleife entfernt leere Zeichenfolgen, bis keine leeren Zeichenfolgen mehr vorhanden sind, und stoppt dann. Ich hatte mir die Frage eigentlich nicht einmal angesehen (nur den Titel), aber ich antwortete mit genau derselben Schleife als Möglichkeit! Wenn Sie aus Gründen des Gedächtnisses keine Verständnisse oder Filter verwenden möchten, ist dies eine sehr pythonische Lösung.– Aaronasterling
2. Oktober 2010 um 12:55 Uhr
Immer noch ein sehr gültiger Punkt, um die Liste, über die Sie iterieren, niemals zu ändern 🙂
– Eduard Lukas
12. Februar 2016 um 21:09 Uhr
@EduardLuca Wenn der Sinn des Iterierens einer Liste darin besteht, sie zu ändern, dann ist das das Gegenteil von dem, was Sie tun sollten. Sie müssen nur darauf achten, dass Sie wissen, dass Sie dadurch kein unerwartetes Verhalten hervorrufen.
– Jacqlyn
1. April 2016 um 16:16 Uhr
@EduardLuca, @JFA: Der Punkt ist, dass er NICHT über eine Liste iteriert. Er würde, wenn er etwas in das Formular geschrieben hätte
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.– Kamion
19. März 2019 um 23:26 Uhr
Sie können Filter verwenden, um die leeren Zeichenfolgen zu entfernen. Der Code sollte in etwa so aussehen…
data = list(filter(None, str_list))
– Jakob Ward
3. Dezember 2020 um 1:26 Uhr