Использование регулярных выражений с "\ s" и выполнение простых завязываний string.split () также удаление других пробелов - таких как переносы строк, возврат каретки, вкладки. Если это не требуется, чтобы только сделать несколько пробелов , я приведу эти примеры.
РЕДАКТИРОВАТЬ: Как я обычно делаю, я спал на этом, и помимо исправления опечатки на последних результатах (v3.3.3 @ 64-бит, не 32 -бит), меня поразило очевидное: тестовая строка была довольно тривиальной.
Итак, я получил ... 11 абзацев, 1000 слов, 6665 байт Lorem Ipsum , чтобы получить более реалистичные временные тесты. Затем я добавил лишние пробелы произвольной длины:
original_string = ''.join(word + (' ' * random.randint(1, 10)) for word in lorem_ipsum.split(' '))
Я также исправил "правильное join
"; если кто-то заботится, то одна строка по существу сделает полосу любых начальных / конечных пробелов, эта исправленная версия сохраняет начальную / конечную пробелы (но только ONE ;-). (Я нашел это, потому что случайно расположенный lorem_ipsum
получил дополнительные пробелы в конце и таким образом потерпел неудачу assert
.)
# setup = '''
import re
def while_replace(string):
while ' ' in string:
string = string.replace(' ', ' ')
return string
def re_replace(string):
return re.sub(r' {2,}' , ' ', string)
def proper_join(string):
split_string = string.split(' ')
# To account for leading/trailing spaces that would simply be removed
beg = ' ' if not split_string[ 0] else ''
end = ' ' if not split_string[-1] else ''
# versus simply ' '.join(item for item in string.split(' ') if item)
return beg + ' '.join(item for item in split_string if item) + end
original_string = """Lorem ipsum ... no, really, it kept going... malesuada enim feugiat. Integer imperdiet erat."""
assert while_replace(original_string) == re_replace(original_string) == proper_join(original_string)
#'''
# while_replace_test
new_string = original_string[:]
new_string = while_replace(new_string)
assert new_string != original_string
# re_replace_test
new_string = original_string[:]
new_string = re_replace(new_string)
assert new_string != original_string
# proper_join_test
new_string = original_string[:]
new_string = proper_join(new_string)
assert new_string != original_string
ПРИМЕЧАНИЕ: "while
версия" сделала копию original_string
, как я полагаю, что после модификации при первом запуске последовательные запуски будут быстрее (если только немного). Поскольку это добавляет время, я добавил эту строковую копию к двум другим, чтобы время показало разницу только в логике. Имейте в виду, что основные stmt
в timeit
экземплярах будут выполняться только один раз ; Первоначально, как я это сделал, цикл while
работал на той же метке, original_string
, поэтому при втором запуске было бы нечего делать. То, как он настроен сейчас, вызывает функцию, используя две разные метки, это не проблема. Я добавил assert
операторов ко всем работникам, чтобы убедиться, что мы что-то меняем каждую итерацию (для тех, кто может быть сомнительным). Например, измените это, и оно сломается:
# while_replace_test
new_string = original_string[:]
new_string = while_replace(new_string)
assert new_string != original_string # will break the 2nd iteration
while ' ' in original_string:
original_string = original_string.replace(' ', ' ')
Tests run on a laptop with an i5 processor running Windows 7 (64-bit).
timeit.Timer(stmt = test, setup = setup).repeat(7, 1000)
test_string = 'The fox jumped over\n\t the log.' # trivial
Python 2.7.3, 32-bit, Windows
test | minum | maximum | average | median
---------------------+------------+------------+------------+-----------
while_replace_test | 0.001066 | 0.001260 | 0.001128 | 0.001092
re_replace_test | 0.003074 | 0.003941 | 0.003357 | 0.003349
proper_join_test | 0.002783 | 0.004829 | 0.003554 | 0.003035
Python 2.7.3, 64-bit, Windows
test | minum | maximum | average | median
---------------------+------------+------------+------------+-----------
while_replace_test | 0.001025 | 0.001079 | 0.001052 | 0.001051
re_replace_test | 0.003213 | 0.004512 | 0.003656 | 0.003504
proper_join_test | 0.002760 | 0.006361 | 0.004626 | 0.004600
Python 3.2.3, 32-bit, Windows
test | minum | maximum | average | median
---------------------+------------+------------+------------+-----------
while_replace_test | 0.001350 | 0.002302 | 0.001639 | 0.001357
re_replace_test | 0.006797 | 0.008107 | 0.007319 | 0.007440
proper_join_test | 0.002863 | 0.003356 | 0.003026 | 0.002975
Python 3.3.3, 64-bit, Windows
test | minum | maximum | average | median
---------------------+------------+------------+------------+-----------
while_replace_test | 0.001444 | 0.001490 | 0.001460 | 0.001459
re_replace_test | 0.011771 | 0.012598 | 0.012082 | 0.011910
proper_join_test | 0.003741 | 0.005933 | 0.004341 | 0.004009
test_string = lorem_ipsum
# Thanks to http://www.lipsum.com/
# "Generated 11 paragraphs, 1000 words, 6665 bytes of Lorem Ipsum"
Python 2.7.3, 32-bit
test | minum | maximum | average | median
---------------------+------------+------------+------------+-----------
while_replace_test | 0.342602 | 0.387803 | 0.359319 | 0.356284
re_replace_test | 0.337571 | 0.359821 | 0.348876 | 0.348006
proper_join_test | 0.381654 | 0.395349 | 0.388304 | 0.388193
Python 2.7.3, 64-bit
test | minum | maximum | average | median
---------------------+------------+------------+------------+-----------
while_replace_test | 0.227471 | 0.268340 | 0.240884 | 0.236776
re_replace_test | 0.301516 | 0.325730 | 0.308626 | 0.307852
proper_join_test | 0.358766 | 0.383736 | 0.370958 | 0.371866
Python 3.2.3, 32-bit
test | minum | maximum | average | median
---------------------+------------+------------+------------+-----------
while_replace_test | 0.438480 | 0.463380 | 0.447953 | 0.446646
re_replace_test | 0.463729 | 0.490947 | 0.472496 | 0.468778
proper_join_test | 0.397022 | 0.427817 | 0.406612 | 0.402053
Python 3.3.3, 64-bit
test | minum | maximum | average | median
---------------------+------------+------------+------------+-----------
while_replace_test | 0.284495 | 0.294025 | 0.288735 | 0.289153
re_replace_test | 0.501351 | 0.525673 | 0.511347 | 0.508467
proper_join_test | 0.422011 | 0.448736 | 0.436196 | 0.440318
Для тривиальной строки может показаться, что цикл while самый быстрый, за которым следует Pythonic string-split / join и регулярное выражение, вытягивающее заднюю часть.
Для нетривиальных строк , кажется, есть еще кое-что, что стоит рассмотреть. 32-битная 2,7? Это регулярное выражение на помощь! 2,7 64-битный? Цикл while
- лучший, с приличным запасом. 32-битный 3.2, идти с "правильной" join
. 64-битная 3.3, цикл while
. Опять же.
В конце концов, можно улучшить производительность , если / где / когда нужно , но всегда лучше запомнить мантру :
- Make It Work
- Сделай все правильно
- Сделай это быстро
IANAL, YMMV, Caveat Emptor!