Каково ваше отвращение к спискам? Они являются неотъемлемой частью языка, и "" .join (list_of_words) является одной из основных идиом для создания списка строк в одну строку, разделенную пробелом.
PaulMcG
3
@ Tom / @ Paul: Для простых строк соединение (строка) будет простым и приятным. Но это становится более сложным, если есть другие пробелы, которые НЕ НАДО беспокоить ... в этом случае решения "while" или regex будут наилучшими. Ниже я разместил строковое соединение, которое было бы «правильным», с результатами тестов по времени для трех способов сделать это.
pythonlarry
Ответы:
529
>>>import re
>>> re.sub(' +',' ','The quick brown fox')'The quick brown fox'
Это решение обрабатывает только одиночные пробелы. Он не заменит табуляцию или другие пробельные символы, обрабатываемые \ s, как в решении nsr81.
Тейлор Лиз
2
Это правда, string.splitтакже обрабатывает все виды пробелов.
Джош Ли
6
Я предпочитаю этот, потому что он фокусируется только на символе пробела и не влияет на символы типа '\ n's.
hhsaffar
2
Да, верно. Но перед этим strip () должно быть сделано. Это удалит пробелы с обоих концов.
Хардик Патель
17
Вы можете использовать re.sub(' {2,}', ' ', 'The quick brown fox')для предотвращения избыточной замены одного пробела на один пробел .
AneesAhmed777
541
foo ваша строка:
" ".join(foo.split())
Имейте в виду, что при этом удаляются «все пробельные символы (пробел, табуляция, новая строка , возврат, подача)» (благодаря hhsaffar см. Комментарии). Т.е., "this is \t a test\n"эффективно будет так "this is a test".
Я бы предпочел изменить это регулярное выражение, чтобы r"\s\s+"оно не пыталось заменить уже одиночные пробелы.
Бен Бланк
19
Если вы хотели такое поведение, то почему бы просто "\s{2,}"вместо обходного пути не знать умеренно продвинутое поведение регулярных выражений?
Крис Латс
2
помните, что sub () не изменяет входную строку s, но возвращает новое значение.
gcb
1
@moose - это оптимизация читабельности, а не производительность. \s+вызовет в строке «заменить один или несколько пробелов пробелом», а не «заменить два или более пробелов пробелом». Первое немедленно заставляет меня остановиться и подумать: «Зачем заменять один пробел одним пробелом? Это глупо». Для меня это (очень незначительный) запах кода. Я на самом деле не ожидаю , что любая разница в производительности вообще между ними, как это будет копировать в новую строку , в любом случае, и должен остановиться и испытание , независимо от того, где пространства копируются из .
Бен Бланк
8
Я бы посоветовал против, \s\s+потому что это не нормализует символ табуляции обратно в обычный пробел. SPACE + TAB действительно заменяется таким образом.
vdboor
51
Использование регулярных выражений с "\ s" и выполнение простых string.split () также удалит другие пробелы, такие как переводы строк, возврат каретки, вкладки. Если это не желательно, чтобы сделать только несколько пробелов , я представляю эти примеры.
original_string =''.join(word +(' '* random.randint(1,10))for word in lorem_ipsum.split(' '))
Однострочник по существу делает полосу любых начальных / конечных пробелов, и он сохраняет начальную / конечную пробелы (но только ОДИН ;-).
# 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 =' 'ifnot split_string[0]else''
end =' 'ifnot 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версия» сделала копию original_string, как я полагаю, однажды измененную при первом запуске, последовательные запуски будут быстрее (хотя бы немного). Поскольку это добавляет время, я добавил эту строковую копию к двум другим, чтобы время показало разницу только в логике. Имейте в виду, что main stmtна timeitэкземплярах будет выполняться только один раз ; Первоначально, как я это сделал, whileцикл работал на одной и той же метке original_string, поэтому при втором запуске было бы нечего делать. То, как он настроен сейчас, вызывает функцию, используя две разные метки, это не проблема. Я добавил assertзаявления всем работникам, чтобы проверить, что мы что-то меняем каждую итерацию (для тех, кто может быть сомнительным). Например, измените это, и это сломается:
Tests run on a laptop with an i5 processor running Windows7(64-bit).
timeit.Timer(stmt = test, setup = setup).repeat(7,1000)
test_string ='The fox jumped over\n\t the log.'# trivialPython2.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.003035Python2.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.004600Python3.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.002975Python3.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"Python2.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.388193Python2.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.371866Python3.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.402053Python3.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цикл. Снова.
В конце концов, можно улучшить производительность, если / где / когда нужно , но всегда лучше помнить мантру :
Я бы предпочел, чтобы вы протестировали простое, так ' '.join(the_string.split())как это обычный вариант использования, но я хотел бы поблагодарить вас за вашу работу!
WEDI
@wedi: По другим комментариям (например, от Gumbo ; user984003 , хотя ее / ее решение является предположительным и не будет работать «во всех случаях»), такое решение не соответствует запросу спрашивающего. Кто-то может использовать .split ('') и comp / gen, но получает больше удовольствия, чтобы иметь дело с пробелами в конце и в конце.
pythonlarry
@wedi: Например: ' '.join(p for p in s.split(' ') if p)<- все еще потерял пробелы вперед / назад, но учитывал несколько пробелов. Чтобы их сохранить, надо делать как parts = s.split(' '); (' ' if not parts[0] else '') + ' '.join(p for p in s.split(' ') if p) + (' ' if not parts[-1] else '')!
pythonlarry
Спасибо @pythonlarry за мантру! и люблю подробный тест! Мне любопытно узнать, изменились ли ваши мысли или взгляды на это с 6 лет?
JayRizzo
Отсутствует версия, в которой используются генераторы
Ли
42
Я должен согласиться с комментарием Пола Макгуайра. Мне,
' '.join(the_string.split())
Крайне предпочтительнее, чем выводить регулярное выражение.
Мои измерения (Linux и Python 2.5) показывают, что split-then-join будет почти в пять раз быстрее, чем выполнение re.sub (...), и еще в три раза быстрее, если вы предварительно скомпилируете регулярное выражение и выполните операцию многократно. И это в какой-то мере легче понять - гораздо больше Pythonic.
Это удаляет завершающие пробелы. Если вы хотите сохранить их, выполните: text [0: 1] + "" .join (text [1: -1] .split ()) + text [-1]
user984003
4
простое регулярное выражение гораздо лучше читать. никогда не оптимизируйте производительность до того, как вам это понадобится.
ГКБ
@gcb: почему бы и нет? Что, если вы ожидаете сценарий с высокой пропускной способностью (например, из-за высокого спроса)? Почему бы не развернуть то, что, как вы ожидаете, будет менее ресурсоемким с самого начала в этом сценарии?
Хасан Бэйг
1
@HassanBaig Если у вас уже есть требования к производительности, то это не слишком преждевременная оптимизация, верно? Я хочу сказать, что когда вам еще не нужно думать о производительности, всегда лучше стремиться к удобочитаемости.
gcb
14
Аналогично предыдущим решениям, но более конкретно: замените два или более пробелов одним:
>>>import re
>>> s ="The fox jumped over the log.">>> re.sub('\s{2,}',' ', s)'The fox jumped over the log.'
Вы также можете использовать технику разделения строк в Pandas DataFrame без необходимости использовать .apply (..), что полезно, если вам нужно быстро выполнить операцию с большим количеством строк. Вот это на одной строке:
В некоторых случаях желательно заменить последовательные вхождения каждого символа пробела одним экземпляром этого символа. Вы бы использовали регулярное выражение с обратными ссылками, чтобы сделать это.
(\s)\1{1,}соответствует любому символу пробела, за которым следует одно или несколько вхождений этого символа. Теперь все, что вам нужно сделать, это указать первую группу ( \1) в качестве замены для совпадения.
Оборачиваем это в функцию:
import re
def normalize_whitespace(string):return re.sub(r'(\s)\1{1,}', r'\1', string)
>>> normalize_whitespace('The fox jumped over the log.')'The fox jumped over the log.'>>> normalize_whitespace('First line\t\t\t \n\n\nSecond line')'First line\t \nSecond line'
>>>import re
>>> str ='this is a string with multiple spaces and tabs'>>> str = re.sub('[ \t]+',' ', str)>>>print str
this is a string with multiple spaces and tabs
Одна строка кода для удаления всех лишних пробелов до, после и внутри предложения:
sentence =" The fox jumped over the log. "
sentence =' '.join(filter(None,sentence.split(' ')))
Объяснение:
Разделить всю строку в список.
Отфильтруйте пустые элементы из списка.
Воссоединить оставшиеся элементы * с одним пробелом
* Остальные элементы должны быть словами или словами с пунктуацией и т. Д. Я не проверял это подробно, но это должно стать хорошей отправной точкой. Всего наилучшего!
def unPretty(S):# Given a dictionary, JSON, list, float, int, or even a string...# return a string stripped of CR, LF replaced by space, with multiple spaces reduced to one.return' '.join(str(S).replace('\n',' ').replace('\r','').split())
Самое быстрое, что вы можете получить для пользовательских строк:
if' 'in text:while' 'in text:
text = text.replace(' ',' ')
Короткое замыкание делает его немного быстрее, чем полный ответ pythonlarry . Пойдите на это, если вы стремитесь к эффективности и строго ищете, чтобы отсеять лишние пробелы в одном пространстве .
У меня есть простой метод, который я использовал в колледже.
line ="I have a nice day."
end =1000while end !=0:
line.replace(" "," ")
end -=1
Это заменит каждый двойной пробел одним пробелом и сделает это 1000 раз. Это означает, что вы можете иметь 2000 дополнительных пробелов и все равно будете работать. :)
Чем это отличается от ответа Анакими (опубликованного более трех лет назад)? Разве это не более сложная версия?
Питер Мортенсен
0
import re
Text=" You can select below trims for removing white space!! BR Aliakbar "# trims all white spacesprint('Remove all space:',re.sub(r"\s+","",Text), sep='')# trims left spaceprint('Remove leading space:', re.sub(r"^\s+","",Text), sep='')# trims right spaceprint('Remove trailing spaces:', re.sub(r"\s+$","",Text), sep='')# trims bothprint('Remove leading and trailing spaces:', re.sub(r"^\s+|\s+$","",Text), sep='')# replace more than one white space in the string with one white spaceprint('Remove more than one space:',re.sub(' +',' ',Text), sep='')
Результат:
Удалить все пробелы: вы можете выбрать нижеприведенные поля для удаления пробелов !! BRAliakbar Удалить начальные пробелы: вы можете выбрать следующие значения для удаления пробелов !! BR Aliakbar
Удалить завершающие пробелы: вы можете выбрать следующие значения для удаления пробелов !! BR Aliakbar Удалить начальные и конечные пробелы: вы можете выбрать следующие ограничения для удаления пробелов !! BR Aliakbar Удалить более одного пробела: Вы можете выбрать ниже трим для удаления пустого пространства! БР Алиакбар
Я не слишком много читал в других примерах, но я только что создал этот метод для объединения нескольких последовательных пробелов.
Он не использует никаких библиотек, и хотя он относительно длинный с точки зрения длины скрипта, он не является сложной реализацией:
def spaceMatcher(command):"""
Function defined to consolidate multiple whitespace characters in
strings to a single space
"""# Initiate index to flag if more than one consecutive character
iteration
space_match =0
space_char =""for char in command:if char ==" ":
space_match +=1
space_char +=" "elif(char !=" ")&(space_match >1):
new_command = command.replace(space_char," ")
space_match =0
space_char =""elif char !=" ":
space_match =0
space_char =""return new_command
command =None
command = str(input("Please enter a command ->"))print(spaceMatcher(command))print(list(spaceMatcher(command)))
Ответы:
источник
string.split
также обрабатывает все виды пробелов.re.sub(' {2,}', ' ', 'The quick brown fox')
для предотвращения избыточной замены одного пробела на один пробел .foo
ваша строка:Имейте в виду, что при этом удаляются «все пробельные символы (пробел, табуляция, новая строка , возврат, подача)» (благодаря hhsaffar см. Комментарии). Т.е.,
"this is \t a test\n"
эффективно будет так"this is a test"
.источник
или
так как пробел перед запятой указан как любимая мозоль в PEP 8 , как упомянул пользователь Martin Thoma в комментариях.
источник
r"\s\s+"
оно не пыталось заменить уже одиночные пробелы."\s{2,}"
вместо обходного пути не знать умеренно продвинутое поведение регулярных выражений?s
, но возвращает новое значение.\s+
вызовет в строке «заменить один или несколько пробелов пробелом», а не «заменить два или более пробелов пробелом». Первое немедленно заставляет меня остановиться и подумать: «Зачем заменять один пробел одним пробелом? Это глупо». Для меня это (очень незначительный) запах кода. Я на самом деле не ожидаю , что любая разница в производительности вообще между ними, как это будет копировать в новую строку , в любом случае, и должен остановиться и испытание , независимо от того, где пространства копируются из .\s\s+
потому что это не нормализует символ табуляции обратно в обычный пробел. SPACE + TAB действительно заменяется таким образом.Использование регулярных выражений с "\ s" и выполнение простых string.split () также удалит другие пробелы, такие как переводы строк, возврат каретки, вкладки. Если это не желательно, чтобы сделать только несколько пробелов , я представляю эти примеры.
Я использовал 11 абзацев, 1000 слов, 6665 байт Lorem Ipsum, чтобы получить реалистичные временные тесты, и использовал лишние пробелы случайной длины во всем:
Однострочник по существу делает полосу любых начальных / конечных пробелов, и он сохраняет начальную / конечную пробелы (но только ОДИН ;-).
ПРИМЕЧАНИЕ:
«Имейте в виду, что mainwhile
версия» сделала копиюoriginal_string
, как я полагаю, однажды измененную при первом запуске, последовательные запуски будут быстрее (хотя бы немного). Поскольку это добавляет время, я добавил эту строковую копию к двум другим, чтобы время показало разницу только в логике.stmt
наtimeit
экземплярах будет выполняться только один раз ; Первоначально, как я это сделал,while
цикл работал на одной и той же меткеoriginal_string
, поэтому при втором запуске было бы нечего делать. То, как он настроен сейчас, вызывает функцию, используя две разные метки, это не проблема. Я добавилassert
заявления всем работникам, чтобы проверить, что мы что-то меняем каждую итерацию (для тех, кто может быть сомнительным). Например, измените это, и это сломается:Для тривиальной строки может показаться, что цикл while является самым быстрым, за которым следует Pythonic string-split / join и регулярное выражение, вытягивающее заднюю часть.
Для нетривиальных строк , кажется, есть еще кое-что, чтобы рассмотреть. 32-битная 2,7? Это регулярное выражение на помощь! 2,7 64-битный?
while
Петля лучше, приличный запас. 32-битная 3.2, переходите с «правильной»join
. 64-битная 3.3, пойти наwhile
цикл. Снова.В конце концов, можно улучшить производительность, если / где / когда нужно , но всегда лучше помнить мантру :
IANAL, YMMV, будьте бдительны!
источник
' '.join(the_string.split())
как это обычный вариант использования, но я хотел бы поблагодарить вас за вашу работу!' '.join(p for p in s.split(' ') if p)
<- все еще потерял пробелы вперед / назад, но учитывал несколько пробелов. Чтобы их сохранить, надо делать какparts = s.split(' '); (' ' if not parts[0] else '') + ' '.join(p for p in s.split(' ') if p) + (' ' if not parts[-1] else '')
!Я должен согласиться с комментарием Пола Макгуайра. Мне,
Крайне предпочтительнее, чем выводить регулярное выражение.
Мои измерения (Linux и Python 2.5) показывают, что split-then-join будет почти в пять раз быстрее, чем выполнение re.sub (...), и еще в три раза быстрее, если вы предварительно скомпилируете регулярное выражение и выполните операцию многократно. И это в какой-то мере легче понять - гораздо больше Pythonic.
источник
Аналогично предыдущим решениям, но более конкретно: замените два или более пробелов одним:
источник
Простая душа
источник
Вы также можете использовать технику разделения строк в Pandas DataFrame без необходимости использовать .apply (..), что полезно, если вам нужно быстро выполнить операцию с большим количеством строк. Вот это на одной строке:
источник
Это удалит все вкладки, новые строки и несколько пробелов с одним пробелом.
источник
Я попробовал следующий метод, и он даже работает в крайнем случае, как:
Но если вы предпочитаете регулярное выражение, это можно сделать так:
Хотя некоторая предварительная обработка должна быть сделана, чтобы удалить конечный и конечный пробел.
источник
Это также, кажется, работает:
Где переменная
s
представляет вашу строку.источник
В некоторых случаях желательно заменить последовательные вхождения каждого символа пробела одним экземпляром этого символа. Вы бы использовали регулярное выражение с обратными ссылками, чтобы сделать это.
(\s)\1{1,}
соответствует любому символу пробела, за которым следует одно или несколько вхождений этого символа. Теперь все, что вам нужно сделать, это указать первую группу (\1
) в качестве замены для совпадения.Оборачиваем это в функцию:
источник
Другая альтернатива:
источник
Одна строка кода для удаления всех лишних пробелов до, после и внутри предложения:
Объяснение:
* Остальные элементы должны быть словами или словами с пунктуацией и т. Д. Я не проверял это подробно, но это должно стать хорошей отправной точкой. Всего наилучшего!
источник
Решение для разработчиков Python:
Вывод:
Original string: Python Exercises Are Challenging Exercises Without extra spaces: Python Exercises Are Challenging Exercises
источник
источник
Самое быстрое, что вы можете получить для пользовательских строк:
Короткое замыкание делает его немного быстрее, чем полный ответ pythonlarry . Пойдите на это, если вы стремитесь к эффективности и строго ищете, чтобы отсеять лишние пробелы в одном пространстве .
источник
Удивительно - никто не опубликовал простую функцию, которая будет намного быстрее, чем ВСЕ другие опубликованные решения. Здесь это идет:
источник
Если вы имеете дело с пробелами, разделение на None не будет включать пустую строку в возвращаемое значение.
5.6.1. Строковые методы, str.split ()
источник
Результаты :
источник
Чтобы удалить пробелы, учитывая начальные, конечные и лишние пробелы между словами, используйте:
Первый
or
имеетor
дело с начальными пробелами, второй - с начальными строками, а последний - с пробелами.Для подтверждения использования, эта ссылка предоставит вам тест.
https://regex101.com/r/meBYli/4
Это должно использоваться с функцией re.split .
источник
У меня есть простой метод, который я использовал в колледже.
Это заменит каждый двойной пробел одним пробелом и сделает это 1000 раз. Это означает, что вы можете иметь 2000 дополнительных пробелов и все равно будете работать. :)
источник
У меня есть простой метод без разделения:
источник
Результат:
Удалить все пробелы: вы можете выбрать нижеприведенные поля для удаления пробелов !! BRAliakbar Удалить начальные пробелы: вы можете выбрать следующие значения для удаления пробелов !! BR Aliakbar
Удалить завершающие пробелы: вы можете выбрать следующие значения для удаления пробелов !! BR Aliakbar Удалить начальные и конечные пробелы: вы можете выбрать следующие ограничения для удаления пробелов !! BR Aliakbar Удалить более одного пробела: Вы можете выбрать ниже трим для удаления пустого пространства! БР Алиакбар
источник
Я не слишком много читал в других примерах, но я только что создал этот метод для объединения нескольких последовательных пробелов.
Он не использует никаких библиотек, и хотя он относительно длинный с точки зрения длины скрипта, он не является сложной реализацией:
источник