Entfernen Sie leere Zeichenfolgen aus einer Liste von Zeichenfolgen

Lesezeit: 9 Minuten

Benutzer-Avatar
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?

  • @Ivo, keine dieser Aussagen ist wahr. Sie sollten niemals eine Liste ändern, die Sie beim Iterieren verwenden for x in list Wenn Sie eine verwenden while 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 geschrieben while 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

Benutzer-Avatar
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 filtersollte 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

Benutzer-Avatar
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

Benutzer-Avatar
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

Benutzer-Avatar
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

Benutzer-Avatar
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


Fassen Sie die besten Antworten zusammen:

1. Leergut beseitigen OHNE Ausschalen:

Das heißt, Zeichenfolgen, die nur aus Leerzeichen bestehen, werden beibehalten:

slist = list(filter(None, slist))

PROs:

  • am einfachsten;
  • am schnellsten (siehe Benchmarks unten).

2. Zur Leergutbeseitigung nach dem Ausschalen …

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 Datensätzen aufgrund des Speichers, im Gegensatz zu den Ergebnissen von @paolo-melchiorre)

2.b … wenn Zeichenketten Leerzeichen zwischen Wörtern enthalten?

slist = list(filter(str.strip, slist))

PROs:

  • am schnellsten;
  • Verständlichkeit des Codes.

Benchmarks auf einer 2018er Maschine:

## 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


Benutzer-Avatar
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

1142480cookie-checkEntfernen Sie leere Zeichenfolgen aus einer Liste von Zeichenfolgen

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy