Я хочу удалить все пустые строки из списка строк в python.
Моя идея выглядит так:
while '' in str_list:
str_list.remove('')
Есть ли еще какой-нибудь питонический способ сделать это?
Я хочу удалить все пустые строки из списка строк в python.
Моя идея выглядит так:
while '' in str_list:
str_list.remove('')
Есть ли еще какой-нибудь питонический способ сделать это?
Я бы использовал 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
strings = ["first", "", "second"]
[x for x in strings if x]
Вывод: ['first', 'second']
имеет для этого специальный вариант:
filter(None, sequence)
Он отфильтрует все элементы, которые будут вычисляться как False. Не нужно использовать фактические вызываемые здесь такие как bool, len и т.д.
Он так же быстро, как map (bool,...)
>>> 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
Ответ от @Ib33X замечательный. Если вы хотите удалить каждую пустую строку, после удаления. вам также нужно использовать метод полосы. В противном случае он также вернет пустую строку, если она имеет пробелы. Например, "" будет действительным и для этого ответа. Таким образом, может быть достигнуто.
strings = ["first", "", "second ", " "]
[x.strip() for x in strings if x.strip()]
Ответ для этого будет ["first", "second"]
.
Если вы хотите использовать метод filter
вместо этого, вы можете сделать
list(filter(lambda item: item.strip(), strings))
. Это дает тот же результат.
Вместо 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"]
В зависимости от размера вашего списка это может быть наиболее эффективным, если вы используете list.remove() вместо создания нового списка:
l = ["1", "", "3", ""]
while True:
try:
l.remove("")
except ValueError:
break
Это имеет то преимущество, что не создает новый список, а недостаток, заключающийся в том, что нужно искать с самого начала каждый раз, хотя в отличие от использования while '' in l
, как было предложено выше, он требует только один раз на вхождение ''
(там безусловно, способ сохранить лучшее из обоих методов, но это сложнее).
Используйте 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
это самый интуитивный метод и делает это в достойное время.
Помните, что если вы хотите сохранить пробелы внутри строки, вы можете непреднамеренно удалить их, используя некоторые подходы. Если у вас есть этот список
['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]
Как сообщает 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()
разделит эти строки.
Чтобы удалить опорожнения после удаления:
slist = map(lambda s: s and s.strip(), slist)
slist = filter(None, slist)
Некоторые PROs:
быстро, выборочно с использованием встроенных функций и понятий.
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
Для списка с комбинацией пробелов и пустых значений используйте простое понимание списка -
>>> 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', '?', '?']
str_list = ['2', '', '2', '', '2', '', '2', '', '2', '']
for item in str_list:
if len(item) < 1:
str_list.remove(item)
Короткий и сладкий.
Прокрутите список существующих строк и затем проверьте пустую строку, если она не пуста, заполните новый список строк непустыми значениями, а затем замените старый список строк на новый список строк
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']