Question Supprimer les chaînes vides d'une liste de chaînes


Je veux supprimer toutes les chaînes vides d'une liste de chaînes en python.

Mon idée ressemble à ceci:

while '' in str_list:
    str_list.remove('')

Y a-t-il une façon plus pythonique de faire ça?


484
2017-10-02 11:21


origine


Réponses:


j'utiliserais filter:

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 renvoie un itérateur de filter, devrait donc être enveloppé dans un appel à list()

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

814
2017-10-02 11:28



Liste des compréhensions

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

Sortie: ['first', 'second']

Edit: raccourci comme suggéré


152
2017-10-02 11:27



Le filtre a une option spéciale pour cela:

filter(None, sequence)

Il filtrera tous les éléments dont la valeur est False. Pas besoin d'utiliser un réel appelable ici, comme bool, len et ainsi de suite.

C'est aussi rapide que la carte (bool, ...)


57
2017-10-02 12:04



>>> lstr = ['hello', '', ' ', 'world', ' ']
>>> lstr
['hello', '', ' ', 'world', ' ']

>>> ' '.join(lstr).split()
['hello', 'world']

>>> filter(None, lstr)
['hello', ' ', 'world', ' ']

Comparer le temps

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

Remarquerez que filter(None, lstr) ne supprime pas les chaînes vides avec un espace ' ', il ne fait que tailler '' tandis que ' '.join(lstr).split() supprime les deux.

Utiliser filter() avec des espaces blancs supprimés, cela prend beaucoup plus de temps:

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

16
2017-10-26 10:06



Au lieu de si x, j'utiliserais si X! = '' Pour éliminer les chaînes vides. Comme ça:

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

Cela préservera le type de données None dans votre liste. En outre, dans le cas où votre liste a des entiers et 0 est l'un d'entre eux, il sera également conservé.

Par exemple,

str_list = [None, '', 0, "Hi", '', "Hello"]
[x for x in str_list if x != '']
[None, 0, "Hi", "Hello"]

9
2017-10-08 14:49



Réponse de @ Ib33X est génial. Si vous souhaitez supprimer toutes les chaînes vides, après les avoir supprimées. vous devez également utiliser la méthode des bandes. Sinon, il retournera la chaîne vide aussi s'il a des espaces blancs. Comme "" sera aussi valable pour cette réponse. Donc, peut être atteint par.

strings = ["first", "", "second ", " "]
[x.strip() for x in strings if x.strip()]

La réponse à cela sera ["first", "second"].
Si vous voulez utiliser filter méthode à la place, vous pouvez faire comme
list(filter(lambda item: item.strip(), strings)). C'est donner le même résultat.


8
2017-08-04 06:01



Utilisation filter:

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

Les inconvénients de l'utilisation du filtre sont les suivants: il est plus lent que les alternatives; aussi, lambda est généralement coûteux.

Ou vous pouvez aller pour le plus simple et le plus itératif de tous:

# 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

C'est la plus intuitive des méthodes et le fait en temps décent.


5
2018-01-07 10:25



Selon la taille de votre liste, cela peut être plus efficace si vous utilisez list.remove () plutôt que de créer une nouvelle liste:

l = ["1", "", "3", ""]

while True:
  try:
    l.remove("")
  except ValueError:
    break

Cela a l’avantage de ne pas créer de nouvelle liste, mais l’inconvénient de devoir rechercher à chaque fois, bien que contrairement à while '' in l comme proposé ci-dessus, il suffit de rechercher une fois par occurrence de '' (il y a certainement un moyen de garder le meilleur des deux méthodes, mais c'est plus compliqué).


4
2017-10-02 11:31



Tel que rapporté par Aziz Alto  filter(None, lstr) ne supprime pas les chaînes vides avec un espace ' ' mais si vous êtes sûr que lstr ne contient que de la chaîne, vous pouvez utiliser filter(str.strip, lstr)

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

Comparer le temps sur mon 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

La solution la plus rapide à supprimer '' et des chaînes vides avec un espace ' ' restes ' '.join(lstr).split().

Comme indiqué dans un commentaire, la situation est différente si vos chaînes contiennent des espaces.

>>> 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']

Tu peux voir ça filter(str.strip, lstr) conserver des chaînes avec des espaces mais ' '.join(lstr).split() va diviser ces chaînes.


4
2017-12-21 16:18



Gardez à l'esprit que si vous voulez garder le espaces blancs dans une chaîne, vous pouvez les supprimer involontairement en utilisant certaines approches. Si vous avez cette liste

['Hello World', '', '', 'Bonjour'] ce que vous voudrez ['bonjour monde', 'bonjour']

d'abord rogner la liste pour convertir tout type d'espace blanc en chaîne vide:

space_to_empty = [x.strip() for x in _text_list]

puis retirez la chaîne vide de leur liste

space_clean_list = [x for x in space_to_empty if x]

2
2018-02-06 19:26