2012-05-23 1 views
3
input = "foo ,,bar ,baz," 
tags = [x.strip() for x in input.split(',') if len(x.strip()) > 0] 

Желаемый результат, очевидно, является списком, в котором нет пустых строк.Можете ли это выражение понимания списка Python быть упрощенным?

Вопрос в духе микро оптимизации; есть ли способ не strip() кандидат x дважды, то есть один раз для теста и один раз для добавления?

Чтобы перефразировать, вы можете создать значение в выражениях, которые могут быть добавлены в список, без выполнения работы дважды?

+0

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

ответ

9

Создание новой строки всегда будет дороже, чем сканирование. x.isspace() вернется после того, как первый не символ пробела встречается

tags = [x.strip() for x in input.split(',') if x and not x.isspace()] 
+0

@ Крис, это лучше? –

+0

Да. И это быстрее, чем у меня. (1,6 секунды против 1,95.) –

+0

@gnibbler Спасибо, это хорошее обоснование. – markdsievers

3
text = 'foo ,,bar ,baz,' 

(я использую text, а не input, как input это имя встроенной команды. Избегайте затенения встроенных команд.)

Прежде всего, len(x.strip()) > 0 можно записать просто (и более эффективно) в качестве x.strip().

tags = [x.strip() for x in text.split(',') if x.strip()] 

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

tags = [x for x in (x.strip() for x in text.split(',')) if x] 

Если вы действительно хотите, вы могли бы даже сделать это функционально ...

tags = filter(bool, map(lambda x: x.strip(), text.split(','))) 

показатели эффективности:

>>> from timeit import timeit 
>>> timeit(lambda: [x.strip() for x in text.split(',') if x.strip()]) 
1.9443869590759277 
>>> timeit(lambda: [x for x in (x.strip() for x in text.split(',')) if x]) 
2.1135239601135254 
>>> timeit(lambda: filter(bool, map(lambda x: x.strip(), text.split(',')))) 
2.52907395362854 

Как вы видите, первое быстрее.

+0

OK спасибо за подсказку, удобно. «В первую очередь ...» подразумевается, что вы можете пролить свет на выполнение работы дважды? – markdsievers

+0

@markdsievers: yep, добавлено сейчас –

+0

@markdsievers: он опрятный, да; но если это был особенно горячий кодовый путь, и поэтому вы заботились о микро-оптимизации, @ gnibbler 'if x, а не x.isspace()' * * быстрее, чем 'if x.strip()'. –

1

это тоже работает ...

text = "foo ,,bar ,baz," 
text.replace(',',' ').split() 
+0

Да, это лучший способ. – georg

+1

Нет, это не работает во всех случаях, например. 'text =" foo ,, bar ,, baz ". Замените ',' пробелами, то есть 'text.replace (',', '') .split()' лучше. – mhawke

+0

@mhawke: thanks – ChessMaster

Смежные вопросы