it-swarm.com.de

Entfernen Sie leere Zeichenfolgen aus einer Liste von Zeichenfolgen

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 eine pythonischere Möglichkeit, dies zu tun?

600
zerodx

Ich würde filter verwenden:

str_list = filter(None, str_list) # fastest
str_list = filter(bool, str_list) # fastest
str_list = filter(len, str_list)  # a bit slower
str_list = filter(lambda item: item, str_list) # slower than list comprehension

Python 3 gibt einen Iterator von filter zurück, sollte also in einen Aufruf von list() eingeschlossen werden

str_list = list(filter(None, str_list)) # fastest

( etc. )

Tests:

>>> timeit('filter(None, str_list)', 'str_list=["a"]*1000', number=100000)
2.4797441959381104
>>> timeit('filter(bool, str_list)', 'str_list=["a"]*1000', number=100000)
2.4788150787353516
>>> timeit('filter(len, str_list)', 'str_list=["a"]*1000', number=100000)
5.2126238346099854
>>> timeit('[x for x in str_list if x]', 'str_list=["a"]*1000', number=100000)
13.354584932327271
>>> timeit('filter(lambda item: item, str_list)', 'str_list=["a"]*1000', number=100000)
17.427681922912598
1009
livibetter

Listenverständnisse

strings = ["first", "", "second"]
[x for x in strings if x]

Ausgabe: ['first', 'second']

Bearbeiten: Wie vorgeschlagen gekürzt

201
Ib33X

filter hat tatsächlich eine spezielle Option dafür:

filter(None, sequence)

Es werden alle Elemente herausgefiltert, die mit False bewertet werden. Es ist nicht erforderlich, ein aktuelles aufrufbares Element wie bool, len usw. zu verwenden.

Es ist genauso schnell wie Map (bool, ...)

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

Beachten Sie, dass filter(None, lstr) keine leeren Zeichenfolgen mit einem Leerzeichen ' ' entfernt, sondern nur '' entfernt, während ' '.join(lstr).split() beide entfernt.

Die Verwendung von filter() mit entfernten Leerzeichen benötigt viel mehr Zeit:

>>> timeit('filter(None, [l.replace(" ", "") for l in lstr])', "lstr=['hello', '', ' ', 'world', ' ']", number=10000000)
18.101892948150635
21
Aziz Alto

Die Antwort von @ Ib33X ist fantastisch. Wenn Sie jede leere Zeichenfolge entfernen möchten, nachdem Sie sie entfernt haben. Sie müssen auch die Strip-Methode verwenden. Andernfalls wird auch die leere Zeichenfolge zurückgegeben, wenn Leerzeichen vorhanden sind. "" 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 hierfür lautet ["first", "second"].
Wenn Sie stattdessen die Methode filter verwenden möchten, können Sie dies tun
list(filter(lambda item: item.strip(), strings)). Dies ist das gleiche Ergebnis.

12
ssi-anik

Anstelle von if x würde ich if X! = '' Verwenden, um nur leere Zeichenfolgen zu entfernen. So was:

str_list = [x for x in str_list if x != '']

Dadurch bleibt der Datentyp None in Ihrer Liste erhalten. Wenn Ihre Liste Ganzzahlen 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"]
11
thiruvenkadam

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", ""]

while True:
  try:
    l.remove("")
  except ValueError:
    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 zu der oben vorgeschlagenen Verwendung von _while '' in l_ nur einmal pro Auftreten von _''_ gesucht werden muss ( Es gibt sicherlich einen Weg, das Beste aus beiden Methoden zu machen, aber es ist komplizierter.

8
Andrew Jaffe

Verwenden Sie filter:

newlist=filter(lambda x: len(x)>0, oldlist) 

Die Nachteile der Verwendung von Filtern bestehen darin, dass sie langsamer sind als Alternativen. Auch lambda ist in der Regel teuer.

Oder Sie entscheiden sich für das Einfachste und das Iterativste von allen:

# I am assuming listtext is the original list containing (possibly) empty items
for 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 Methode und geht in angemessener Zeit.

7
Aamir Mushtaq

Beachten Sie, dass Sie die Leerzeichen in einer Zeichenfolge, wenn Sie sie beibehalten möchten, mit einigen Methoden möglicherweise unbeabsichtigt entfernen. Wenn Sie diese Liste haben

['hallo welt', '', '', 'hallo'] was du willst ['hallo welt', 'hallo']

trimmen 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]
6
Reihan_amn

Wie von Aziz Altofilter(None, lstr) entfernt keine leeren Zeichenfolgen mit einem Leerzeichen ' ', aber wenn Sie sicher sind, dass lstr nur Zeichenfolgen enthält Sie können filter(str.strip, lstr) verwenden

>>> lstr = ['hello', '', ' ', 'world', ' ']
>>> lstr
['hello', '', ' ', 'world', ' ']
>>> ' '.join(lstr).split()
['hello', 'world']
>>> filter(str.strip, lstr)
['hello', 'world']

Vergleiche mal auf meinem PC

>>> from timeit import timeit
>>> timeit('" ".join(lstr).split()', "lstr=['hello', '', ' ', 'world', ' ']", number=10000000)
3.356455087661743
>>> timeit('filter(str.strip, lstr)', "lstr=['hello', '', ' ', 'world', ' ']", number=10000000)
5.276503801345825

Die schnellste Lösung, um '' und leere Zeichenfolgen mit einem Leerzeichen ' ' zu entfernen, bleibt ' '.join(lstr).split().

Wie in einem Kommentar berichtet, ist die Situation anders, wenn Ihre Zeichenfolgen Leerzeichen enthalten.

>>> lstr = ['hello', '', ' ', 'world', '    ', 'see you']
>>> lstr
['hello', '', ' ', 'world', '    ', 'see you']
>>> ' '.join(lstr).split()
['hello', 'world', 'see', 'you']
>>> filter(str.strip, lstr)
['hello', 'world', 'see you']

Sie können sehen, dass filter(str.strip, lstr) Zeichenfolgen mit Leerzeichen beibehalten, aber ' '.join(lstr).split() diese Zeichenfolgen aufteilt.

5

Leergut nach dem Abisolieren beseitigen:

slist = map(lambda s: s and s.strip(), slist)
slist = filter(None, slist)

Einige Profis:

  • faul, basierend auf Generatoren, um Speicher zu sparen;
  • anständige Verständlichkeit des Codes;
  • schnell, selektiv mit eingebauten und Verständnis.

    def f1(slist):
        slist = [s and s.strip() for s in slist]
        return list(filter(None, slist))
    
    def f2(slist):
        slist = [s and s.strip() for s in slist]
        return [s for s in slist if s]
    
    
    def f3(slist):
        slist = map(lambda s: s and s.strip(), slist)
        return list(filter(None, slist))
    
    def f4(slist):
        slist = map(lambda s: s and s.strip(), slist)
        return [s for s in slist if s]
    
    %timeit f1(words)
    10000 loops, best of 3: 106 µs per loop
    
    %timeit f2(words)
    10000 loops, best of 3: 126 µs per loop
    
    %timeit f3(words)
    10000 loops, best of 3: 165 µs per loop
    
    %timeit f4(words)
    10000 loops, best of 3: 169 µs per loop
    
0
ankostis