假设此字符串:
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行),而无需拆分并进入列表?
Answers:
>>> import re
>>> re.sub(' +', ' ', 'The quick brown fox')
'The quick brown fox'
string.split
还可以处理各种空白。
re.sub(' {2,}', ' ', 'The quick brown fox')
来防止将single-space替换为single-space。
foo
是您的字符串:
" ".join(foo.split())
请注意,尽管这样做会删除“所有空白字符(空格,制表符,换行符,返回符,换页符)”(由于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)
正如使用者Martin Thoma在评论中所提到的,因为逗号前的空格在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(' '))
一衬垫将基本上做任何前/后间隔的条带,并且它保留一个前/后空间(但只ONE ;-)。
# 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字符串拆分/连接,而regex则拉到后面。
对于非平凡的字符串,似乎还有更多需要考虑的地方。32位2.7?正则表达式可以解救!2.7 64位?一while
环是最好的,通过一个体面的保证金。32位3.2,使用“ proper” 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 '')
!
我必须同意保罗·麦圭尔的评论。对我来说,
' '.join(the_string.split())
比使用正则表达式要好得多。
我的测量结果(Linux和Python 2.5)显示split-then-join几乎比执行“ re.sub(...)”快五倍,如果预编译一次regex并执行操作,则快三倍。多次。它是比较容易理解的任何措施- 很多更Python。
import re
string = re.sub('[ \t\n]+', ' ', 'The quick brown \n\n \t fox')
这将删除所有选项卡,换行和带有单个空格的多个空格。
在某些情况下,它是希望用的单个实例来代替每个空格字符的连续出现该字符。您将使用带有反向引用的正则表达式来执行此操作。
(\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'
适用于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(' ', ' ')
短路使其比pythonlarry的综合答案要快一些。如果您追求效率,并严格寻求除掉单个空间种类的多余空白,则可以这样做。
如果您要处理的是空格,则在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='')
结果:
删除所有空间:您可以选择下面的修剪来删除空白!BRAliakbar删除前导空间:您可以选择下面的修剪来删除空白!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)))