Giả sử chuỗi này:
The fox jumped over the log.
Trở thành:
The fox jumped over the log.
Đơn giản nhất (1-2 dòng) để đạt được điều này, mà không cần tách và đi vào danh sách là gì?
Giả sử chuỗi này:
The fox jumped over the log.
Trở thành:
The fox jumped over the log.
Đơn giản nhất (1-2 dòng) để đạt được điều này, mà không cần tách và đi vào danh sách là gì?
Câu trả lời:
>>> import re
>>> re.sub(' +', ' ', 'The quick brown fox')
'The quick brown fox'
string.split
cũng xử lý tất cả các loại khoảng trắng.
re.sub(' {2,}', ' ', 'The quick brown fox')
để ngăn chặn sự thay thế dự phòng của không gian đơn với không gian đơn .
foo
là chuỗi của bạn:
" ".join(foo.split())
Được cảnh báo mặc dù điều này loại bỏ "tất cả các ký tự khoảng trắng (dấu cách, tab, dòng mới, trả về, formfeed)" (nhờ hhsaffar , xem bình luận). Tức là, "this is \t a test\n"
cuối cùng sẽ có hiệu quả như "this is a test"
.
import re
s = "The fox jumped over the log."
re.sub("\s\s+" , " ", s)
hoặc là
re.sub("\s\s+", " ", s)
vì khoảng trắng trước dấu phẩy được liệt kê dưới dạng peeve vật nuôi trong PEP 8 , như được đề cập bởi người dùng Martin Thoma trong các bình luận.
r"\s\s+"
để nó không cố gắng thay thế các không gian đơn lẻ.
"\s{2,}"
thay vì một cách giải quyết vì không biết hành vi regex vừa phải nâng cao?
s
, nhưng trả về giá trị mới.
\s+
sẽ khiến dòng này đọc "thay thế một hoặc nhiều khoảng trắng bằng một khoảng trắng", thay vì "thay thế hai hoặc nhiều khoảng trắng bằng một khoảng trắng". Cái trước ngay lập tức khiến tôi dừng lại và nghĩ "Tại sao lại thay thế một không gian bằng một không gian? Điều đó thật ngớ ngẩn." Đối với tôi, đó là một mùi mã (rất nhỏ). Tôi thực sự không mong đợi có sự khác biệt về hiệu năng giữa cả hai, vì dù sao nó cũng sẽ được sao chép thành một chuỗi mới, và phải dừng lại và kiểm tra bất kể không gian được sao chép từ đâu .
\s\s+
vì điều này sẽ không bình thường hóa một nhân vật TAB trở lại không gian bình thường. SPACE + TAB được thay thế theo cách này.
Sử dụng biểu thức chính quy với "\ s" và thực hiện các chuỗi đơn giản.split () cũng sẽ xóa các khoảng trắng khác - như dòng mới, trả về vận chuyển, tab. Trừ khi điều này là mong muốn, để chỉ làm nhiều không gian , tôi trình bày các ví dụ này.
Tôi đã sử dụng 11 đoạn, 1000 từ, 6665 byte Lorem Ipsum để có các bài kiểm tra thời gian thực tế và sử dụng các khoảng trắng thừa có độ dài ngẫu nhiên trong suốt:
original_string = ''.join(word + (' ' * random.randint(1, 10)) for word in lorem_ipsum.split(' '))
Về cơ bản, một lớp lót sẽ thực hiện một dải của bất kỳ khoảng trắng đầu / cuối nào và nó giữ một khoảng trắng ở đầu / cuối (nhưng chỉ MỘT ;-).
# 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
LƯU Ý: " Hãy nhớ rằng chính while
Phiên bản" đã tạo một bản sao của original_string
, như tôi tin rằng một khi được sửa đổi trong lần chạy đầu tiên, các lần chạy liên tiếp sẽ nhanh hơn (nếu chỉ một chút). Khi điều này thêm thời gian, tôi đã thêm bản sao chuỗi này vào hai bản kia để thời gian chỉ cho thấy sự khác biệt trong logic. stmt
trên các timeit
trường hợp sẽ chỉ được thực hiện một lần ; cách ban đầu tôi đã làm điều này, while
vòng lặp hoạt động trên cùng một nhãn original_string
, do đó, lần chạy thứ hai, sẽ không có gì để làm. Cách thức thiết lập bây giờ, gọi một hàm, sử dụng hai nhãn khác nhau, đó không phải là vấn đề. Tôi đã thêm các assert
báo cáo cho tất cả các công nhân để xác minh rằng chúng tôi thay đổi điều gì đó mỗi lần lặp (đối với những người có thể không rõ ràng). Ví dụ, thay đổi điều này và nó phá vỡ:
# 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
Đối với chuỗi tầm thường, có vẻ như vòng lặp while là nhanh nhất, theo sau là chuỗi phân tách / nối Pythonic và regex kéo lên phía sau.
Đối với các chuỗi không tầm thường , dường như có thêm một chút để xem xét. 32-bit 2.7? Đó là regex để giải cứu! 2.7 64 bit? Một while
vòng lặp là tốt nhất, bởi một lề tốt. 32-bit 3.2, đi với "đúng" join
. 64-bit 3.3, đi một while
vòng lặp. Lần nữa.
Cuối cùng, người ta có thể cải thiện hiệu suất nếu / ở đâu / khi cần , nhưng tốt nhất là luôn nhớ câu thần chú :
IANAL, YMMV, Emptor Caveat!
' '.join(the_string.split())
vì đây là trường hợp sử dụng thông thường nhưng tôi muốn nói lời cảm ơn vì công việc của bạn!
' '.join(p for p in s.split(' ') if p)
<- vẫn bị mất khoảng trắng chì / dấu, nhưng chiếm nhiều khoảng trắng. Để giữ chúng, phải làm như thế nào parts = s.split(' '); (' ' if not parts[0] else '') + ' '.join(p for p in s.split(' ') if p) + (' ' if not parts[-1] else '')
!
Tôi phải đồng ý với nhận xét của Paul McGuire. Với tôi,
' '.join(the_string.split())
là rất thích hợp để đánh bại một regex.
Các phép đo của tôi (Linux và Python 2.5) cho thấy phép chia tách sau đó nhanh hơn gần năm lần so với thực hiện "re.sub (...)" và vẫn nhanh hơn ba lần nếu bạn biên dịch lại biểu thức chính quy một lần và thực hiện thao tác nhiều lần. Và đó là bằng bất kỳ biện pháp nào dễ hiểu hơn - nhiều Pythonic hơn.
import re
string = re.sub('[ \t\n]+', ' ', 'The quick brown \n\n \t fox')
Điều này sẽ loại bỏ tất cả các tab, dòng mới và nhiều khoảng trắng với khoảng trắng đơn.
Tôi đã thử phương pháp sau và thậm chí nó còn hoạt động với trường hợp cực đoan như:
str1=' I live on earth '
' '.join(str1.split())
Nhưng nếu bạn thích một biểu thức chính quy, nó có thể được thực hiện như sau:
re.sub('\s+', ' ', str1)
Mặc dù một số tiền xử lý phải được thực hiện để loại bỏ dấu cách và không gian kết thúc.
Trong một số trường hợp, mong muốn thay thế các lần xuất hiện liên tiếp của mọi ký tự khoảng trắng bằng một thể hiện duy nhất của ký tự đó . Bạn sẽ sử dụng một biểu thức chính quy với phản hồi để làm điều đó.
(\s)\1{1,}
phù hợp với bất kỳ ký tự khoảng trắng, theo sau là một hoặc nhiều lần xuất hiện của ký tự đó. Bây giờ, tất cả những gì bạn cần làm là chỉ định nhóm đầu tiên (\1
) làm thay thế cho trận đấu.
Bao bọc điều này trong một chức năng:
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'
Một dòng mã để loại bỏ tất cả các khoảng trắng thừa trước, sau và trong câu:
sentence = " The fox jumped over the log. "
sentence = ' '.join(filter(None,sentence.split(' ')))
Giải trình:
* Các yếu tố còn lại phải là từ hoặc từ có dấu chấm câu, v.v. Tôi đã không kiểm tra rộng rãi điều này, nhưng đây sẽ là điểm khởi đầu tốt. Tất cả là tốt nhất!
Giải pháp cho nhà phát triển Python:
import re
text1 = 'Python Exercises Are Challenging Exercises'
print("Original string: ", text1)
print("Without extra spaces: ", re.sub(' +', ' ', text1))
Đầu ra:
Original string: Python Exercises Are Challenging Exercises
Without extra spaces: Python Exercises Are Challenging Exercises
Tốc độ nhanh nhất bạn có thể nhận được cho các chuỗi do người dùng tạo là:
if ' ' in text:
while ' ' in text:
text = text.replace(' ', ' ')
Việc đoản mạch làm cho nó nhanh hơn một chút so với câu trả lời toàn diện của pythonlarry . Hãy làm điều này nếu bạn đang theo đuổi hiệu quả và đang nghiêm túc tìm cách loại bỏ các khoảng trắng thừa của nhiều loại không gian duy nhất .
Khá ngạc nhiên - không ai đăng chức năng đơn giản sẽ nhanh hơn nhiều so với TẤT CẢ các giải pháp được đăng khác. Nó đi từ đây:
def compactSpaces(s):
os = ""
for c in s:
if c != " " or os[-1] != " ":
os += c
return os
Nếu đó là khoảng trắng bạn đang xử lý, thì việc chia tách trên Không sẽ không bao gồm một chuỗi trống trong giá trị được trả về.
string = 'This is a string full of spaces and taps'
string = string.split(' ')
while '' in string:
string.remove('')
string = ' '.join(string)
print(string)
Kết quả :
Đây là một chuỗi đầy không gian và vòi
Để xóa khoảng trắng, hãy xem xét hàng đầu, dấu và thêm khoảng trắng ở giữa các từ, sử dụng:
(?<=\s) +|^ +(?=\s)| (?= +[\n\0])
Các or
giao dịch đầu tiên liên quan đến không gian trắng hàng đầu, or
giao dịch thứ hai bắt đầu chuỗi trắng hàng đầu và giao dịch cuối cùng liên quan đến không gian trắng kéo dài.
Để chứng minh việc sử dụng, liên kết này sẽ cung cấp cho bạn một bài kiểm tra.
https://regex101.com/r/meBYli/4
Điều này được sử dụng với chức năng re.split .
Tôi có phương pháp đơn giản mà tôi đã sử dụng ở trường đại học.
line = "I have a nice day."
end = 1000
while end != 0:
line.replace(" ", " ")
end -= 1
Điều này sẽ thay thế mọi không gian đôi bằng một không gian duy nhất và sẽ thực hiện 1000 lần. Nó có nghĩa là bạn có thể có thêm 2000 không gian và vẫn sẽ hoạt động. :)
Tôi đã có một phương pháp đơn giản mà không cần tách:
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='')
Kết quả:
Xóa tất cả không gian: Youcanselectbelowtrimsforremovingwhitespace !! BRAliakbar Xóa không gian hàng đầu: Bạn có thể chọn bên dưới để xóa khoảng trắng !! BR Aliakbar
Xóa các khoảng trắng ở cuối: Bạn có thể chọn các viền bên dưới để xóa khoảng trắng !! BR Aliakbar Xóa các khoảng trắng ở đầu và cuối: Bạn có thể chọn các ô bên dưới để xóa khoảng trắng !! BR Aliakbar Xóa nhiều hơn một khoảng trắng: Bạn có thể chọn các viền bên dưới để xóa khoảng trắng !! BR Aliakbar
Tôi chưa đọc nhiều vào các ví dụ khác, nhưng tôi vừa tạo phương thức này để hợp nhất nhiều ký tự không gian liên tiếp.
Nó không sử dụng bất kỳ thư viện nào và trong khi nó tương đối dài về độ dài tập lệnh, thì nó không phải là một triển khai phức tạp:
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)))