Припустимо, цей рядок:
The fox jumped over the log.
Перетворення в:
The fox jumped over the log.
Що найпростіше (1-2 рядки) досягти цього, не розбиваючи і не переходячи на списки?
Припустимо, цей рядок:
The fox jumped over the log.
Перетворення в:
The fox jumped over the log.
Що найпростіше (1-2 рядки) досягти цього, не розбиваючи і не переходячи на списки?
Відповіді:
>>> import re
>>> re.sub(' +', ' ', 'The quick brown fox')
'The quick brown fox'
string.split
також обробляє всі види пробілів.
re.sub(' {2,}', ' ', 'The quick brown fox')
для запобігання надмірної заміни однопросторового на однопросторовий .
foo
ваша рядок:
" ".join(foo.split())
Будьте попереджені, хоча це видаляє "всі символи пробілу (пробіл, вкладка, новий рядок, повернення, formfeed)" (завдяки hhsaffar , див. Коментарі). Тобто, "this is \t a test\n"
фактично вийде як "this is a test"
.
import re
s = "The fox jumped over the log."
re.sub("\s\s+" , " ", s)
або
re.sub("\s\s+", " ", s)
оскільки простір перед комою занесено до домашнього улюбленця в PEP 8 , про що згадує користувач Мартін Тома в коментарях.
r"\s\s+"
так, щоб він не намагався замінити вже єдині пробіли.
"\s{2,}"
замість вирішення проблеми, що не знала помірковано розвиненої регексу?
s
, але повертає нове значення.
\s+
призведе до того, що рядок буде читати "замінити один чи більше пробілів пробілом", а не "замінити два чи більше пробілів пробілом". Колишній одразу змушує мене зупинитися і подумати: "Навіщо замінювати один простір одним? Це дурне". Для мене це (дуже другорядний) запах коду. Я на насправді не очікую , що будь-яка різниця в продуктивності взагалі між ними, як це буде копіювати в новий рядок , в будь-якому випадку, і повинен зупинитися і випробування , незалежно від того, де простору копіюються з .
\s\s+
оскільки це не нормалізує символ TAB назад у звичайний простір. SPACE + TAB замінюється таким чином.
Використання шрифтів з "\ s" та простого string.split () також видалить інші пробіли - наприклад, нові рядки, повернення каретки, вкладки. Якщо це не бажано, щоб тільки зробити кілька прогалин , я уявляю ці приклади.
Я використовував 11 абзаців, 1000 слів, 6665 байт Lorem Ipsum, щоб отримати реалістичні тести часу та використовував додаткові пробіли випадкової довжини протягом:
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 = ' ' 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
Для тривіальної струни, здається, що цикл у той час є найшвидшим, за ним слід пітонічна струна-розділ / з'єднання та витяг, що підтягується ззаду.
Для нетривіальних рядків , здається, варто ще трохи розглянути. 32-розрядні 2,7? Це виручка на допомогу! 2,7 64-розрядні? while
Петля краще, пристойний запас. 32-бітний 3.2, перейдіть з "належним" join
. 64-бітний 3.3, перейдіть до while
циклу. Знову.
Зрештою, можна покращити продуктивність, якщо / де / коли потрібно , але найкраще пам’ятати про мантру :
IANAL, YMMV, Caveat Emptor!
' '.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 '')
!
Я маю згоду з коментарем Пола Макгуайра. Для мене, мені,
' '.join(the_string.split())
є переважним перевагою, ніж вибивання регексу.
Мої вимірювання (Linux і Python 2.5) показують, що розділення, а потім приєднання буде майже в п’ять разів швидше, ніж робити "re.sub (...)", і все-таки втричі швидше, якщо попередньо скомпілювати регекс і виконати операцію кілька разів. І це будь-якою мірою простіше зрозуміти - набагато більше піфонічного.
Ви також можете використовувати техніку розбиття рядків у програмі Pandas DataFrame, не використовуючи .apply (..), що корисно, якщо вам потрібно швидко виконати операцію на великій кількості рядків. Ось це в одному рядку:
df['message'] = (df['message'].str.split()).str.join(' ')
import re
string = re.sub('[ \t\n]+', ' ', 'The quick brown \n\n \t fox')
Це видалить усі вкладки, нові лінії та декілька пробілів з одним пробілом.
Я спробував наступний метод, і він працює навіть у крайньому випадку, наприклад:
str1=' I live on earth '
' '.join(str1.split())
Але якщо ви віддаєте перевагу регулярному вираженню, це можна зробити так:
re.sub('\s+', ' ', str1)
Хоча для попередньої обробки та закінчення простору необхідно виконати деяку попередню обробку.
У деяких випадках бажано замінити послідовне виникнення кожного символу пробілу одним екземпляром цього символу. Для цього ви використовуєте регулярний вираз із зворотними посиланнями.
(\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'
Один рядок коду для видалення всіх зайвих пробілів до, після та в реченні:
sentence = " The fox jumped over the log. "
sentence = ' '.join(filter(None,sentence.split(' ')))
Пояснення:
* Решта елементів повинні бути слова або слова з розділовими знаками і т. Д. Я не перевіряв це широко, але це повинно бути гарною відправною точкою. Все найкраще!
Рішення для розробників Python:
import re
text1 = 'Python Exercises Are Challenging Exercises'
print("Original string: ", text1)
print("Without extra spaces: ", re.sub(' +', ' ', text1))
Вихід:
Original string: Python Exercises Are Challenging Exercises
Without extra spaces: Python Exercises Are Challenging Exercises
Найшвидше ви можете отримати для створених користувачем рядків:
if ' ' in text:
while ' ' in text:
text = text.replace(' ', ' ')
Коротке замикання робить це трохи швидше, ніж вичерпна відповідь пітонарі . Займіться цим, якщо ви досягли ефективності і чітко прагнете вилучити зайві пробіли з одного простору .
Досить дивно - ніхто не розмістив просту функцію, яка буде набагато швидшою, ніж ВСІ інші розміщені рішення. Ось це іде:
def compactSpaces(s):
os = ""
for c in s:
if c != " " or os[-1] != " ":
os += c
return os
Якщо це пробіл, з яким ви маєте справу, розбиття на None не включатиме порожню рядок у повернене значення.
string = 'This is a string full of spaces and taps'
string = string.split(' ')
while '' in string:
string.remove('')
string = ' '.join(string)
print(string)
Результати :
Це рядок, повний пробілів і кранів
Щоб видалити пробіл, враховуючи провідні, відсталі та зайвий пробіл між словами, використовуйте:
(?<=\s) +|^ +(?=\s)| (?= +[\n\0])
Перший or
стосується провідних білих просторів, другийor
стосується початку білого простору, який веде до рядків, а останній стосується пробілу білого простору.
Для підтвердження використання це посилання надасть вам тест.
https://regex101.com/r/meBYli/4
Це потрібно використовувати з функцією re.split .
У мене є простий метод, який я використовував у коледжі.
line = "I have a nice day."
end = 1000
while end != 0:
line.replace(" ", " ")
end -= 1
Це замінить кожен подвійний простір на один простір і зробить це 1000 разів. Це означає, що ви можете мати 2000 додаткових просторів і все одно працюватимете. :)
У мене простий метод без розщеплення:
a = "Lorem Ipsum Darum Diesrum!"
while True:
count = a.find(" ")
if count > 0:
a = a.replace(" ", " ")
count = a.find(" ")
continue
else:
break
print(a)
import re
Text = " You can select below trims for removing white space!! BR Aliakbar "
# trims all white spaces
print('Remove all space:',re.sub(r"\s+", "", Text), sep='')
# trims left space
print('Remove leading space:', re.sub(r"^\s+", "", Text), sep='')
# trims right space
print('Remove trailing spaces:', re.sub(r"\s+$", "", Text), sep='')
# trims both
print('Remove leading and trailing spaces:', re.sub(r"^\s+|\s+$", "", Text), sep='')
# replace more than one white space in the string with one white space
print('Remove more than one space:',re.sub(' +', ' ',Text), sep='')
Результат:
Вилучіть увесь простір: Ви можете вибрати вибрані нижче рамки, щоб зняти простір !! BR Aliakbar
Видалення пробілів: Ви можете вибрати нижню частину обрізки для видалення пробілів !! 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)))