@ Иво, ни одно из этих утверждений не соответствует действительности. Вы никогда не должны изменять список, который вы используете для итерации. for x in listЕсли вы используете, while loopто это нормально. Показанный цикл удалит пустые строки, пока не останется больше пустых строк, а затем остановится. На самом деле я даже не посмотрел на вопрос (только название), но я ответил точно так же, как это возможно! Если вы не хотите использовать понимание или фильтры ради памяти, это очень питонное решение.
Ааронастерлинг
4
Тем не менее, очень важный момент - никогда не менять список, который вы повторяете :)
Эдуард Лука,
1
@EduardLuca, если цель итерации по списку состоит в том, чтобы изменить его, то это противоположно тому, что вы должны сделать. Вам просто нужно быть осторожным, чтобы вы знали, что при этом вы не вызываете неожиданного поведения.
JFA
1
@EduardLuca, @JFA: Дело в том, что он НЕ повторяется ни по одному списку. Он бы, если бы он написал что-то в форме for var in list:, но здесь он написал while const in list:. который не перебирает ничего. это просто повторяет один и тот же код, пока условие не станет ложным.
Если вы что нажата для выполнения, itertool«sifilter даже faster- >>> timeit('filter(None, str_list)', 'str_list=["a"]*1000', number=100000)2.3468542098999023; >>> timeit('itertools.ifilter(None, str_list)', 'str_list=["a"]*1000', number=100000)0.04442191123962402,
Хамфри Богарт
4
@cpburnz Очень верно. Однако ifilterрезультаты оцениваются лениво, а не за один раз - я бы сказал, что в большинстве случаев ifilterэто лучше. Интересно, что использование filterпо-прежнему быстрее, чем завернуть ifilterв listхотя.
Хамфри Богарт
3
Если вы сделаете это со списком чисел, обратите внимание, что нули также будут удалены (примечание: я использовал только первые 3 метода), поэтому вам понадобится альтернативный метод.
SnoringFrog
2
Это фокусируется только на скорости, а не на том, насколько питонным является решение (вопрос, который был задан). Понимание списка - это питонное решение, и фильтр следует использовать только в том случае, если профилирование доказало, что listcomp является узким местом.
Тритий
3
@ whoever-упоминания о-или-подразумеваемом-Python-3, пожалуйста, просто отредактируйте и обновите ответ. Мы обсуждали только Python 2, когда задавался этот вопрос, даже Python 3 был выпущен почти 2 года назад. Но обновите результаты Python 2 и 3.
Мне нравится это решение, потому что оно легко адаптируется. Если мне нужно , чтобы удалить не только пустые строки , но строки, которые только пробелы, например: [x for x in strings if x.strip()].
Бонд
67
Фильтр на самом деле имеет специальную опцию для этого:
filter(None, sequence)
Это отфильтрует все элементы, которые оцениваются как False. Нет необходимости использовать фактический вызываемый объект, такой как bool, len и так далее.
это не сработает, если у вас есть место среди строки слова. например: ['hello world', '', 'hello', '']. >> ['helloworld', '', 'hello', ''] Есть ли у вас какое-либо другое решение, позволяющее сохранить пробелы внутри элемента в списке, но удалить другие?
Reihan_amn
Обратите внимание, что filter(None, lstr)пустые строки не удаляются с пробелом' ' Да, потому что это не пустая строка.
AMC
15
Ответ от @ Ib33X потрясающий. Если вы хотите удалить каждую пустую строку, после удаления. вам нужно использовать метод стрип тоже. В противном случае он также вернет пустую строку, если у него есть пробелы. Мол, "" будет действительным и для этого ответа. Таким образом, может быть достигнуто путем.
strings =["first","","second "," "][x.strip()for x in strings if x.strip()]
Ответ на это будет ["first", "second"].
Если вы хотите использовать filterметод вместо этого, вы можете сделать как
list(filter(lambda item: item.strip(), strings)). Это дает тот же результат.
Если в ваших списках есть разные типы (кроме «Нет»), у вас могут быть большие проблемы.
Тритий
Какие типы? Я пробовал с int и другими числовыми типами, строками, списками, кортежами, множествами и None и никаких проблем там нет. Я мог видеть, что, если есть какие-либо определенные пользователем типы, которые не поддерживают метод str, может возникнуть проблема. Должен ли я беспокоиться о других?
Триувенкадам
1
Если у вас есть str_list = [None, '', 0, "Hi", '', "Hello"], это признак плохо разработанного приложения. Вы не должны иметь более одного интерфейса (типа) и None в одном списке.
Tritium21
3
Получение данных из БД? список аргументов для функции при выполнении автоматического тестирования?
Триувенкадам
3
Это обычно кортежи.
Tritium21,
7
В зависимости от размера вашего списка, это может быть наиболее эффективным, если вы используете list.remove (), а не создаете новый список:
l =["1","","3",""]whileTrue:try:
l.remove("")exceptValueError:break
Преимущество этого состоит не в создании нового списка, а в недостатке необходимости искать каждый раз с самого начала, хотя в отличие от использования, while '' in lкак предложено выше, поиск требует только один раз в каждом случае ''(безусловно, есть способ сохранить лучшее из оба метода, но это сложнее).
Вы можете редактировать список на месте, выполнив ary[:] = [e for e in ary if e]. Гораздо чище и не использует исключения для управления потоком.
Кшиштоф Карский
2
Ну, это не совсем "на месте" - я уверен, что это создает новый список и просто присваивает его старому имени.
Эндрю Джаффе
Это работает очень плохо, так как хвост данных перетасовывается в памяти при каждом удалении. Лучше убрать все в один удар.
Вим
7
Помните, что если вы хотите сохранить пробелы внутри строки , вы можете непреднамеренно удалить их, используя некоторые подходы. Если у вас есть этот список
['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]
если вы хотите сохранить пробелы внутри строки, вы можете непреднамеренно удалить их, используя некоторые подходы. Вам нравится такой подход?
AMC
Спасибо, чувак, это сработало для меня с небольшими изменениями. то естьspace_clean_list = [x.strip() for x in y if x.strip()]
Мухаммед Мехран Хан Аттари
6
Используйте filter:
newlist=filter(lambda x: len(x)>0, oldlist)
Недостатки использования фильтра, как указано выше, заключаются в том, что он медленнее альтернатив; Кроме того, lambdaобычно это дорого.
Или вы можете пойти на самый простой и самый итеративный из всех:
# I am assuming listtext is the original list containing (possibly) empty itemsfor item in listtext:if item:
newlist.append(str(item))# You can remove str() based on the content of your original list
это самый интуитивный из методов и делает это в приличное время.
Добро пожаловать в ТАК. Вы не были проигнорированы. Вы не подвергались нападению со стороны какого-либо необычного даунотера. Вам дали отзыв. Усиление: предложенный вами первый аргумент для фильтра хуже, чем тот, lambda x: len(x)который хуже, чем lambda x : xкоторый является худшим из 4 решений в выбранном ответе. Правильное функционирование является предпочтительным, но не достаточным. Наведите курсор на кнопку понижения: там написано: «Этот ответ бесполезен».
Джон Мачин
5
Как сообщает Aziz, Altofilter(None, lstr) не удаляет пустые строки с пробелом, ' 'но если вы уверены, что lstr содержит только строку, вы можете использоватьfilter(str.strip, lstr)
for x in list
Если вы используете,while loop
то это нормально. Показанный цикл удалит пустые строки, пока не останется больше пустых строк, а затем остановится. На самом деле я даже не посмотрел на вопрос (только название), но я ответил точно так же, как это возможно! Если вы не хотите использовать понимание или фильтры ради памяти, это очень питонное решение.for var in list:
, но здесь он написалwhile const in list:
. который не перебирает ничего. это просто повторяет один и тот же код, пока условие не станет ложным.Ответы:
Я бы использовал
filter
:Python 3 возвращает итератор из
filter
, поэтому должен быть заключен в вызовlist()
источник
itertool
«sifilter
даже faster->>> timeit('filter(None, str_list)', 'str_list=["a"]*1000', number=100000)
2.3468542098999023
;>>> timeit('itertools.ifilter(None, str_list)', 'str_list=["a"]*1000', number=100000)
0.04442191123962402
,ifilter
результаты оцениваются лениво, а не за один раз - я бы сказал, что в большинстве случаевifilter
это лучше. Интересно, что использованиеfilter
по-прежнему быстрее, чем завернутьifilter
вlist
хотя.Использование понимания списка - самый питонский способ:
Если список необходимо изменить на месте, поскольку существуют другие ссылки, которые должны видеть обновленные данные, используйте назначение среза:
источник
[x for x in strings if x.strip()]
.Фильтр на самом деле имеет специальную опцию для этого:
Это отфильтрует все элементы, которые оцениваются как False. Нет необходимости использовать фактический вызываемый объект, такой как bool, len и так далее.
Это так же быстро, как карта (bool, ...)
источник
Сравнить время
Обратите внимание, что
filter(None, lstr)
пустые строки не удаляются с пробелом' '
, они удаляются только''
при удалении' '.join(lstr).split()
обоих.Чтобы использовать
filter()
строки без пробелов, это займет намного больше времени:источник
filter(None, lstr)
пустые строки не удаляются с пробелом' '
Да, потому что это не пустая строка.Ответ от @ Ib33X потрясающий. Если вы хотите удалить каждую пустую строку, после удаления. вам нужно использовать метод стрип тоже. В противном случае он также вернет пустую строку, если у него есть пробелы. Мол, "" будет действительным и для этого ответа. Таким образом, может быть достигнуто путем.
Ответ на это будет
["first", "second"]
.Если вы хотите использовать
filter
метод вместо этого, вы можете сделать какlist(filter(lambda item: item.strip(), strings))
. Это дает тот же результат.источник
Вместо if x я бы использовал if X! = '', Чтобы просто удалить пустые строки. Нравится:
Это сохранит тип данных None в вашем списке. Кроме того, если в вашем списке есть целые числа и 0 среди них одно, оно также будет сохранено.
Например,
источник
str_list = [None, '', 0, "Hi", '', "Hello"]
, это признак плохо разработанного приложения. Вы не должны иметь более одного интерфейса (типа) и None в одном списке.В зависимости от размера вашего списка, это может быть наиболее эффективным, если вы используете list.remove (), а не создаете новый список:
Преимущество этого состоит не в создании нового списка, а в недостатке необходимости искать каждый раз с самого начала, хотя в отличие от использования,
while '' in l
как предложено выше, поиск требует только один раз в каждом случае''
(безусловно, есть способ сохранить лучшее из оба метода, но это сложнее).источник
ary[:] = [e for e in ary if e]
. Гораздо чище и не использует исключения для управления потоком.Помните, что если вы хотите сохранить пробелы внутри строки , вы можете непреднамеренно удалить их, используя некоторые подходы. Если у вас есть этот список
['hello world', '', '', 'hello'] что вы можете захотеть ['hello world', 'hello']
сначала обрежьте список, чтобы преобразовать любой тип пробела в пустую строку:
затем удалите пустую строку из списка
источник
space_clean_list = [x.strip() for x in y if x.strip()]
Используйте
filter
:Недостатки использования фильтра, как указано выше, заключаются в том, что он медленнее альтернатив; Кроме того,
lambda
обычно это дорого.Или вы можете пойти на самый простой и самый итеративный из всех:
это самый интуитивный из методов и делает это в приличное время.
источник
lambda x: len(x)
который хуже, чемlambda x : x
который является худшим из 4 решений в выбранном ответе. Правильное функционирование является предпочтительным, но не достаточным. Наведите курсор на кнопку понижения: там написано: «Этот ответ бесполезен».Как сообщает Aziz, Alto
filter(None, lstr)
не удаляет пустые строки с пробелом,' '
но если вы уверены, что lstr содержит только строку, вы можете использоватьfilter(str.strip, lstr)
Сравните время на моем компьютере
Самое быстрое решение для удаления
''
и очистки строк с пробелом' '
остается' '.join(lstr).split()
.Как сообщается в комментарии, ситуация отличается, если ваши строки содержат пробелы.
Вы можете видеть, что
filter(str.strip, lstr)
сохраняются строки с пробелами, но' '.join(lstr).split()
разбиваются эти строки.источник
join
решение разделит строки пробелом, а фильтр - нет. Спасибо за ваш комментарий Я улучшил свой ответ.Подведите лучшие ответы:
1. Ликвидация пустых БЕЗ зачистки:
Таким образом, строки всего пространства сохраняются:
PROs:
2. Устранить пустоты после зачистки ...
2.a ... когда строки НЕ содержат пробелов между словами:
PROs:
2.b ... когда строки содержат пробелы между словами?
PROs:
Тесты на машине 2018 года:
источник
s and s.strip()
можно упростить до всегоs.strip()
.s and s.strip()
нужен, если мы хотим полностью воспроизвестиfilter(None, words)
принятый ответ. Я исправил x2 пример функции выше и удалил x2 плохих.Для списка с комбинацией пробелов и пустых значений используйте простое понимание списка -
Итак, вы можете видеть, что в этом списке есть комбинация пробелов и нулевых элементов. Используя фрагмент -
источник