Misalkan string ini:
The fox jumped over the log.
Berubah menjadi:
The fox jumped over the log.
Apa yang paling sederhana (1-2 baris) untuk mencapai ini, tanpa membelah dan masuk ke daftar?
Misalkan string ini:
The fox jumped over the log.
Berubah menjadi:
The fox jumped over the log.
Apa yang paling sederhana (1-2 baris) untuk mencapai ini, tanpa membelah dan masuk ke daftar?
Jawaban:
>>> import re
>>> re.sub(' +', ' ', 'The quick brown fox')
'The quick brown fox'
string.split
juga menangani semua jenis ruang putih.
re.sub(' {2,}', ' ', 'The quick brown fox')
untuk mencegah penggantian ruang tunggal dengan ruang tunggal berlebih .
foo
adalah string Anda:
" ".join(foo.split())
Berhati-hatilah meskipun ini menghapus "semua karakter spasi putih (spasi, tab, baris baru, kembali, formfeed)" (terima kasih kepada hhsaffar , lihat komentar). Yaitu, "this is \t a test\n"
secara efektif akan berakhir sebagai "this is a test"
.
import re
s = "The fox jumped over the log."
re.sub("\s\s+" , " ", s)
atau
re.sub("\s\s+", " ", s)
karena spasi sebelum koma terdaftar sebagai pet peeve di PEP 8 , sebagaimana disebutkan oleh pengguna Martin Thoma dalam komentar.
r"\s\s+"
sehingga tidak mencoba mengganti spasi yang sudah tunggal.
"\s{2,}"
solusi untuk tidak mengetahui perilaku regex yang cukup canggih?
s
, tetapi mengembalikan nilai baru.
\s+
akan menyebabkan baris membaca "ganti satu atau lebih spasi dengan spasi", daripada "ganti dua atau lebih spasi dengan spasi". Yang pertama segera membuat saya berhenti dan berpikir, "Mengapa mengganti satu ruang dengan satu ruang? Itu konyol." Bagi saya, itu bau kode (sangat kecil). Aku benar-benar tidak akan berharap ada menjadi perbedaan kinerja sama sekali antara dua, karena itu akan menyalin ke dalam sebuah string baru pula, dan harus berhenti dan uji terlepas dari di mana ruang yang disalin dari .
\s\s+
karena ini tidak akan menormalkan karakter TAB kembali ke ruang normal. SPACE + TAB diganti dengan cara ini.
Menggunakan regex dengan "\" dan melakukan string.split () yang sederhana juga akan menghapus spasi putih lainnya - seperti baris baru, carriage return, tab. Kecuali jika ini diinginkan, untuk hanya melakukan beberapa spasi , saya menyajikan contoh-contoh ini.
Saya menggunakan 11 paragraf, 1000 kata, 6665 byte Lorem Ipsum untuk mendapatkan tes waktu yang realistis dan menggunakan ruang ekstra panjang acak di seluruh:
original_string = ''.join(word + (' ' * random.randint(1, 10)) for word in lorem_ipsum.split(' '))
One-liner pada dasarnya akan melakukan strip dari setiap ruang terdepan / tambahan, dan mempertahankan ruang terdepan / tertinggal (tetapi hanya SATU ;-).
# 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
CATATAN: " Perlu diingat bahwa utama while
Versi" membuat salinan original_string
, karena saya percaya sekali dimodifikasi pada jalankan pertama, berjalan berturut-turut akan lebih cepat (jika hanya sedikit). Karena ini menambah waktu, saya menambahkan salinan string ini ke dua lainnya sehingga waktu menunjukkan perbedaan hanya dalam logika. stmt
pada timeit
kasus hanya akan dieksekusi sekali ; cara asli saya melakukan ini, while
loop bekerja pada label yang sama original_string
, sehingga menjalankan kedua, tidak ada yang bisa dilakukan. Cara pengaturannya sekarang, memanggil fungsi, menggunakan dua label berbeda, itu tidak masalah. Saya telah menambahkan assert
pernyataan kepada semua pekerja untuk memverifikasi bahwa kami mengubah sesuatu setiap iterasi (bagi mereka yang mungkin ragu). Misalnya, ubah ke ini dan rusak:
# 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
Untuk string sepele, akan terlihat bahwa loop sementara adalah yang tercepat, diikuti oleh string-split / join Pythonic, dan regex menarik ke belakang.
Untuk string non-sepele , sepertinya ada sedikit lebih untuk dipertimbangkan. 32-bit 2,7? Ini regex untuk menyelamatkan! 2,7 64-bit? Sebuah while
lingkaran yang terbaik, dengan margin yang layak. 32-bit 3.2, pergi dengan "tepat" join
. 64-bit 3.3, lakukan while
perulangan. Lagi.
Pada akhirnya, seseorang dapat meningkatkan kinerja jika / di mana / kapan dibutuhkan , tetapi yang terbaik adalah mengingat mantra :
IANAL, YMMV, Caveat Emptor!
' '.join(the_string.split())
karena ini adalah kasus penggunaan biasa tetapi saya ingin mengucapkan terima kasih atas pekerjaan Anda!
' '.join(p for p in s.split(' ') if p)
<- masih kehilangan spasi awal / akhir, tetapi menyumbang beberapa ruang. Untuk menjaganya, pasti suka parts = s.split(' '); (' ' if not parts[0] else '') + ' '.join(p for p in s.split(' ') if p) + (' ' if not parts[-1] else '')
!
Saya harus setuju dengan komentar Paul McGuire. Untuk saya,
' '.join(the_string.split())
jauh lebih baik daripada mencabut regex.
Pengukuran saya (Linux dan Python 2.5) menunjukkan split-then-join menjadi hampir lima kali lebih cepat daripada melakukan "re.sub (...)", dan masih tiga kali lebih cepat jika Anda mengkompilasi ulang regex sekali dan melakukan operasi beberapa kali. Dan dengan cara apa pun lebih mudah dipahami - jauh lebih Pythonic.
Anda juga dapat menggunakan teknik pemisahan string dalam Pandaf DataFrame tanpa perlu menggunakan .apply (..), yang berguna jika Anda perlu melakukan operasi dengan cepat pada sejumlah besar string. Ini dia dalam satu baris:
df['message'] = (df['message'].str.split()).str.join(' ')
import re
string = re.sub('[ \t\n]+', ' ', 'The quick brown \n\n \t fox')
Ini akan menghapus semua tab, garis baru dan banyak spasi putih dengan spasi putih tunggal.
Saya telah mencoba metode berikut dan bahkan bekerja dengan kasus ekstrim seperti:
str1=' I live on earth '
' '.join(str1.split())
Tetapi jika Anda lebih suka ekspresi reguler, itu bisa dilakukan sebagai:
re.sub('\s+', ' ', str1)
Meskipun beberapa preprocessing harus dilakukan untuk menghilangkan ruang trailing dan ending.
Dalam beberapa kasus itu diinginkan untuk menggantikan kejadian berturut-turut setiap karakter spasi dengan satu contoh dari yang karakter. Anda akan menggunakan ekspresi reguler dengan referensi untuk melakukan itu.
(\s)\1{1,}
cocok dengan karakter spasi putih apa pun, diikuti oleh satu atau lebih kemunculan karakter itu. Sekarang, yang perlu Anda lakukan adalah menentukan grup pertama ( \1
) sebagai pengganti pertandingan.
Membungkus ini dalam suatu fungsi:
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'
Satu baris kode untuk menghapus semua spasi tambahan sebelum, sesudah, dan dalam kalimat:
sentence = " The fox jumped over the log. "
sentence = ' '.join(filter(None,sentence.split(' ')))
Penjelasan:
* Elemen yang tersisa harus kata-kata atau kata-kata dengan tanda baca, dll. Saya tidak menguji ini secara ekstensif, tetapi ini harus menjadi titik awal yang baik. Semua yang terbaik!
Solusi untuk pengembang Python:
import re
text1 = 'Python Exercises Are Challenging Exercises'
print("Original string: ", text1)
print("Without extra spaces: ", re.sub(' +', ' ', text1))
Keluaran:
Original string: Python Exercises Are Challenging Exercises
Without extra spaces: Python Exercises Are Challenging Exercises
Yang tercepat yang Anda dapatkan untuk string yang dibuat pengguna adalah:
if ' ' in text:
while ' ' in text:
text = text.replace(' ', ' ')
Hubungan arus pendek membuatnya sedikit lebih cepat daripada jawaban komprehensif pythonlarry . Pergi untuk ini jika Anda mengejar efisiensi dan benar-benar mencari untuk menyingkirkan ruang putih tambahan dari berbagai ruang tunggal .
Cukup mengejutkan - tidak ada yang memposting fungsi sederhana yang akan jauh lebih cepat daripada SEMUA solusi diposting lainnya. Ini dia:
def compactSpaces(s):
os = ""
for c in s:
if c != " " or os[-1] != " ":
os += c
return os
Jika spasi putih yang Anda hadapi, pemisahan pada None tidak akan memasukkan string kosong dalam nilai yang dikembalikan.
string = 'This is a string full of spaces and taps'
string = string.split(' ')
while '' in string:
string.remove('')
string = ' '.join(string)
print(string)
Hasil :
Ini adalah string yang penuh dengan spasi dan ketukan
Untuk menghilangkan ruang putih, dengan mempertimbangkan spasi di depan, di belakang, dan ruang putih ekstra di antara kata-kata, gunakan:
(?<=\s) +|^ +(?=\s)| (?= +[\n\0])
Kesepakatan pertama or
dengan ruang putih terdepan, yang kedua or
berkaitan dengan dimulainya string ruang putih terkemuka, dan yang terakhir berkaitan dengan ruang putih tertinggal.
Untuk bukti penggunaan, tautan ini akan memberi Anda tes.
https://regex101.com/r/meBYli/4
Ini akan digunakan dengan fungsi re.split .
Saya punya metode sederhana yang saya gunakan di perguruan tinggi.
line = "I have a nice day."
end = 1000
while end != 0:
line.replace(" ", " ")
end -= 1
Ini akan menggantikan setiap ruang ganda dengan satu ruang dan akan melakukannya 1000 kali. Ini berarti Anda dapat memiliki 2000 ruang ekstra dan masih akan berfungsi. :)
Saya punya metode sederhana tanpa pemisahan:
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='')
Hasil:
Hapus semua ruang: Youcanselectbelowtrimsforremovingwhitespace !! BRAliakbar Hapus ruang terdepan: Anda dapat memilih trim di bawah ini untuk menghilangkan ruang putih !! BR Aliakbar
Hapus spasi tambahan: Anda dapat memilih trim di bawah ini untuk menghilangkan spasi putih !! BR Aliakbar Hapus spasi depan dan belakang: Anda dapat memilih trim di bawah ini untuk menghilangkan spasi putih !! BR Aliakbar Hapus lebih dari satu ruang: Anda dapat memilih trim di bawah ini untuk menghilangkan ruang putih !! BR Aliakbar
Saya belum banyak membaca contoh-contoh lain, tetapi saya baru saja membuat metode ini untuk menggabungkan beberapa karakter spasi berturut-turut.
Itu tidak menggunakan perpustakaan apa pun, dan sementara itu relatif panjang dalam hal panjang skrip, itu bukan implementasi yang kompleks:
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)))