Возможно ли понимание этого списка в Python?

У меня есть отношения любви/ненависти со списком. С одной стороны, я думаю, что они аккуратные и элегантные. С другой стороны, я ненавижу их читать. (особенно те, которые я не писал) Я обычно придерживаюсь правила, сделайте его доступным для чтения, пока не потребуется скорость. Поэтому мой вопрос действительно академичен на данный момент.

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

stations = []
for row in data:
    if row.strip():
        stations.append(row.strip())

Что переводится в этот список:

stations = [row.strip() for row in data if row.strip()]

Это работает достаточно хорошо, но мне кажется, что я делаю полосу дважды. Я догадался, что .strip() на самом деле не требуется дважды и, как правило, медленнее, чем просто назначать переменную.

stations = []
for row in data:
    blah = row.strip()
    if blah:
        stations.append(blah)

Оказывается, я был прав.

> Striptwice list comp 14.5714301669     
> Striptwice loop 17.9919670399
> Striponce loop 13.0950567955

Timeit показывает между двумя сегментами цикла, второй (полоса один раз) работает быстрее. Здесь нет ничего удивительного. Я удивляюсь, что понимание списка лишь незначительно медленнее, хотя оно делает полосу дважды.

Мой вопрос: Есть ли способ написать представление списка, которое только делает полосу раз?



Результаты:

Вот результаты выбора предложений

# @JonClements & @ErikAllik
> Striptonce list comp 10.7998494348
# @adhie
> Mapmethod loop 14.4501044569

Ответы

Ответ 1

Вложенные понимания могут быть сложными для чтения, поэтому мое первое предпочтение было бы следующим:

stripped = (x.strip() for x in data)
stations = [x for x in stripped if x]

Или, если вы inline stripped, вы получаете одно (вложенное) понимание списка:

stations = [x for x in (x.strip() for x in data) if x]

Обратите внимание, что первое/внутреннее понимание является фактически генераторным выражением, которое, другими словами, является ленивым списком; это чтобы избежать повторения дважды.

Ответ 2

Существует - сначала создать генератор разделенных строк, затем используйте это:

stations = [row for row in (row.strip() for row in data) if row]

Вы также можете записать его без comp, например (swap to imap и удалить list для Python 2.x):

stations = list(filter(None, map(str.strip, data)))

Ответ 3

Примените полосу ко всем элементам с помощью map() и затем фильтруйте.

[item for item in map(lambda x: x.strip(), list) if item]