Подтвердить что ты не робот

Учет списка с дублированным вызовом функции

Я хочу преобразовать строку, такую ​​как:

'   1   ,   2  ,    ,   ,   3   '

в список непустых элементов:

['1', '2', '3']

Мое решение - это понимание этого списка:

print [el.strip() for el in mystring.split(",") if el.strip()]

Просто интересно, есть ли хороший питонический способ написать это понимание, не вызывая el.strip() дважды?

4b9b3361

Ответ 1

Вы можете использовать генератор внутри понимания списка:

  [x for x in (el.strip() for el in mylist.split(",")) if x]
#             \__________________ ___________________/
#                                v
#                        internal generator

Таким образом, генератор будет обеспечивать разделенные элементы, и мы будем перебирать генератор и проверять правдоподобие. Таким образом, мы сохраняем вызовы el.strip().

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

  [x for x in map(str.strip, mylist.split(",")) if x]
#             \______________ ________________/
#                            v
#                           map

Но это в основном то же самое (хотя логика генератора - по-моему - лучше инкапсулирована).

Ответ 2

В качестве простой альтернативы получить список непустых элементов (в дополнение к предыдущим хорошим ответам):

import re

s = '   1   ,   2  ,    ,   ,   3   '
print(re.findall(r'[^\s,]+', s))

Выход:

['1', '2', '3']

Ответ 3

Как о некотором regex извлечь все числа из строки

import re

a = '   1   ,   2  ,    ,   ,   3   '
print(re.findall(r'\d+', a))

Вывод:

['1', '2', '3']

Ответ 4

Только в одной строке кода, которая будет как-то кратким, вы получите. Конечно, если вы хотите получить причудливый вы можете попробовать функциональный подход:

filter(lambda x: x, map(lambda x: x.strip(), mylist.split(',')))

Но это дает вам краткость в обмен на видимость

Ответ 5

Перейдите в полный функционал с помощью map и filter, используя:

s = '   1   ,   2  ,    ,   ,   3   '
res = filter(None, map(str.strip, s.split(',')))

хотя похоже на ответ @omu_negru, это позволяет избежать использования lambda, которые, возможно, довольно уродливы, но также замедляют работу.

Аргумент None для фильтрации преобразуется в: фильтр по истине, по существу x for x in iterable if x, тогда как map просто отображает метод str.strip (который имеет значение split по умолчанию для пробелов) для итерации, полученной из s.split(',').

На Python 2, где filter по-прежнему возвращает список, этот подход должен легко устранять другие подходы в скорости.


В Python 3 нужно было бы использовать:

res = [*filter(None, map(str.strip, s.split(',')))]

чтобы вернуть список.

Ответ 6

Если вы импортировали "re", то re.split() будет работать:

import re
s='   1   ,   2  ,    ,   ,   3   '
print ([el for el in re.split(r"[, ]+",s) if el])
['1', '2', '3']

Если строки, разделенные пробелами (без промежуточной запятой), не должны разделяться, то это будет работать:

import re
s=' ,,,,,     ,,,,  1   ,   2  ,    ,   ,   3,,,,,4   5, 6   '
print ([el for el in re.split(r"\s*,\s*",s.strip()) if el])
['1', '2', '3', '4   5', '6']

Ответ 7

Список понятий замечателен, но не запрещено использовать более одной строки кода! Вы могли бы даже - запретить небо - использовать цикл for!

result = []
for el in mystring.split(",")
    x = el.strip()
    if x:
        result.append(x)

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

all_terms = [el.strip() for el in mystring.split(",")]
non_empty_terms = [x for x in all_terms if x]

Некоторые из других ответов, конечно, короче, но я не уверен, что любой из них проще/легче понять. На самом деле, я думаю, что лучший ответ - это только один из ваших вопросов, потому что повторение в этом случае довольно незначительное.