Удалить пустые строки из списка строк - PullRequest
586 голосов
/ 02 октября 2010

Я хочу удалить все пустые строки из списка строк в Python.

Моя идея выглядит следующим образом:

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

Есть ли еще какой-нибудь питонный способ сделать это?1006 *

Ответы [ 14 ]

988 голосов
/ 02 октября 2010

Я бы использовал 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 возвращает итератор из filter, поэтому его следует заключить в вызов list()

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

( и т. Д. )

Тесты:

>>> 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
199 голосов
/ 02 октября 2010

Список понятий

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

Выход: ['first', 'second']

Редактировать: укорочено в соответствии с предложением

61 голосов
/ 02 октября 2010
Фильтр

на самом деле имеет специальную опцию для этого:

filter(None, sequence)

Он отфильтрует все элементы, имеющие значение False.Здесь нет необходимости использовать фактический вызываемый объект, такой как bool, len и т. Д.

Он одинаково быстр, как map (bool, ...)

21 голосов
/ 26 октября 2015
>>> lstr = ['hello', '', ' ', 'world', ' ']
>>> lstr
['hello', '', ' ', 'world', ' ']

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

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

Время сравнения

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

Обратите внимание, что filter(None, lstr) не удаляет пустые строки с пробелом ' ', он только удаляет '', в то время как ' '.join(lstr).split() удаляет оба.

Чтобы использовать filter() с удаленными пустыми строками, требуется намного больше времени:

>>> timeit('filter(None, [l.replace(" ", "") for l in lstr])', "lstr=['hello', '', ' ', 'world', ' ']", number=10000000)
18.101892948150635
12 голосов
/ 04 августа 2016

Ответ от @ Ib33X потрясающий.Если вы хотите удалить каждую пустую строку, после удаления.вам нужно использовать метод стрип тоже.В противном случае он также вернет пустую строку, если у него есть пробелы.Мол, "" будет действительным и для этого ответа.Таким образом, может быть достигнуто с помощью.

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

Ответ для этого будет ["first", "second"].Если вы хотите использовать метод filter вместо этого, вы можете сделать какlist(filter(lambda item: item.strip(), strings)).Это дает тот же результат.

11 голосов
/ 08 октября 2013

Вместо x, я бы использовал if X! = '', Чтобы просто удалить пустые строки.Например:

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

Это сохранит тип данных None в вашем списке.Кроме того, если в вашем списке есть целые числа и 0 среди них одно, оно также будет сохранено.

Например,

str_list = [None, '', 0, "Hi", '', "Hello"]
[x for x in str_list if x != '']
[None, 0, "Hi", "Hello"]
8 голосов
/ 02 октября 2010

В зависимости от размера вашего списка, это может быть наиболее эффективным, если вы используете list.remove (), а не создаете новый список:

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

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

Это имеет преимущество не в том, чтобы создавать новый список, а в том, что он требует поиска с самого начала каждый раз, хотя в отличие от использования while '' in l, как предложено выше, поиск требует только один раз для каждого вхождения '' (там это, конечно, способ сохранить лучшее из обоих методов, но он более сложный).

7 голосов
/ 07 января 2012

Использовать filter:

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

Недостатки использования фильтра, как указано, заключается в том, что он медленнее, чем альтернативы;Кроме того, lambda обычно является дорогостоящим.

Или вы можете пойти на самый простой и самый итеративный из всех:

# 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

это самый интуитивный из методов и делает это в приличное время.

6 голосов
/ 06 февраля 2018

Помните, что если вы хотите сохранить пробелы в строке , вы можете непреднамеренно удалить их, используя некоторые подходы. Если у вас есть этот список

['hello world', '', '', 'hello'] что ты можешь хотеть ['привет мир', 'привет']

сначала обрежьте список, чтобы преобразовать любой тип пробела в пустую строку:

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

затем удалите пустую строку из списка

space_clean_list = [x for x in space_to_empty if x]
5 голосов
/ 21 декабря 2016

Как сообщает Aziz Alto filter(None, lstr) не удаляет пустые строки с пробелом ' ', но если вы уверены, что lstr содержит только строку, вы можете использовать filter(str.strip, lstr)

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

Сравните время на моем компьютере

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

Самое быстрое решение для удаления '' и пустых строк с пробелом ' ' остается ' '.join(lstr).split().

Как сообщается в комментарии,ситуация другая, если ваши строки содержат пробелы.

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

Вы можете видеть, что filter(str.strip, lstr) сохраняет строки с пробелами, но ' '.join(lstr).split() будет разбивать эти строки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...