Удалить пустые строки из списка строк

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

Моя идея выглядит так:

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

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

Ответ 1

Я бы использовал 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

Ответ 3

Фильтр

имеет для этого специальный вариант:

filter(None, sequence)

Он отфильтрует все элементы, которые будут вычисляться как False. Не нужно использовать фактические вызываемые здесь такие как bool, len и т.д.

Он так же быстро, как map (bool,...)

Ответ 4

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

Ответ 5

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

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

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

Ответ 6

Вместо x, я бы использовал, если 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"]

Ответ 7

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

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

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

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

Ответ 8

Используйте 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

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

Ответ 9

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

['hello world', '', '', 'hello'] что вы можете захотеть ['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]

Ответ 10

Как сообщает 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() разделит эти строки.

Ответ 11

Чтобы удалить опорожнения после удаления:

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

Некоторые PROs:

  • lazy, основанный на генераторах, для сохранения памяти;
  • достойная понятность кода;
  • быстро, выборочно с использованием встроенных функций и понятий.

    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
    

Ответ 12

Для списка с комбинацией пробелов и пустых значений используйте простое понимание списка -

>>> s = ['I', 'am', 'a', '', 'great', ' ', '', '  ', 'person', '!!', 'Do', 'you', 'think', 'its', 'a', '', 'a', '', 'joke', '', ' ', '', '?', '', '', '', '?']

Итак, вы можете видеть, что этот список содержит комбинацию пробелов и нулевых элементов. Использование фрагмента -

>>> d = [x for x in s if x.strip()]
>>> d
>>> d = ['I', 'am', 'a', 'great', 'person', '!!', 'Do', 'you', 'think', 'its', 'a', 'a', 'joke', '?', '?']

Ответ 13

str_list = ['2', '', '2', '', '2', '', '2', '', '2', '']

for item in str_list:
    if len(item) < 1:  
        str_list.remove(item)

Короткий и сладкий.

Ответ 14

Прокрутите список существующих строк и затем проверьте пустую строку, если она не пуста, заполните новый список строк непустыми значениями, а затем замените старый список строк на новый список строк

Ответ 15

filter(None, str) не удаляет пустые строки с пробелом '', это только сокращает '' и ''.

join(str).split() удаляет оба. но если ваш элемент списка имеет пространство, то он изменит ваши элементы списка также потому, что он соединяет сначала все ваши элементы списка, а затем выплевывает их по пространству, поэтому вы должны использовать: -

str = ['hello', '', ' ', 'world', ' ']
print filter(lambda x:x != '', filter(lambda x:x != ' ', str))

Он удалит оба и не будет влиять на ваши элементы. Например: -

str = ['hello', '', ' ', 'world ram', ' ']
print  ' '.join(lstr).split()
print filter(lambda x:x != '', filter(lambda x:x != ' ', lstr))

вывод: -

['hello', 'world', 'ram'] < -------------- вывод ' '.join(lstr).split()
['hello', 'world ram']