假设这个字符串:
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
也可以处理各种类型的空格。 - Josh Leere.sub(' {2,}', ' ', 'The quick brown fox')
来防止将单个空格重复替换为单个空格。 - AneesAhmed777re.sub('\s{2,}', ' ', text)
将会用单个空格替换掉所有连续的空白字符(制表符、换行符等)。 - otakufoo
是你的字符串:
" ".join(foo.split())
请注意,这将删除所有空格字符(空格、制表符、换行符、回车符、换页符)(感谢hhsaffar的评论)。也就是说,"this is \t a test\n"
最终将变成"this is a test"
。
r"\s\s+"
,以便它不会尝试替换已经是单个空格的情况。 - Ben Blank"\s{2,}"
而不是为了避免不知道中等难度的正则表达式行为而采用一个变通方法呢? - Chris Lutzs
,而是返回一个新的值。 - gcb\s\s+
,因为这种方式无法将TAB字符标准化为普通空格。 使用空格和制表符的组合会被替换成普通空格。 - vdboorstrip()
函数(也称为修剪)来删除字符串中的空格,因为您可能不希望保留字符串开头和结尾的空格。 - Christophe Roussyoriginal_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
,因为我认为修改后的第一次运行后,后续的运行将更快(即使只有一点点)。由于这会增加时间,所以我在其他两种方式中也添加了字符串副本,以便时间只显示逻辑上的差异。 请记住,在timeit
实例上主要的stmt
语句只会执行一次; 我最初的做法是,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字符串拆分/连接,最后是正则表达式。
对于非平凡的字符串,似乎需要考虑更多因素。32位2.7?正则表达式来拯救!2.7 64位?使用while
循环效果最佳,优势明显。32位3.2,选择“适当”的join
。64位3.3,使用while
循环。再次。
最终,可以在需要的时候改善性能,但最好记住口头禅:
本人不是法律专家,你的情况可能有所不同,请自行斟酌!
' '.join(the_string.split())
пјҢеӣ дёәиҝҷжҳҜйҖҡеёёзҡ„з”Ёжі•пјҢдҪҶжҲ‘иҝҳжҳҜиҰҒж„ҹи°ўдҪ зҡ„е·ҘдҪңпјҒ - 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我必须同意Paul McGuire的评论。对于我来说,
' '.join(the_string.split())
使用split-then-join方法要比使用正则表达式更为可取。
我的测试结果(在Linux系统下,Python版本为2.5)表明,使用split-then-join方法几乎比使用“re.sub(...)”快五倍,并且如果你预编译一次正则表达式然后多次操作,仍然比其快三倍。而且使用split-then-join方法更易于理解,更符合Python语言风格。
正则表达式
更难读,所以对我来说这是一个偏好问题。 Split
和 join
很常用,而且不需要额外导入模块。当涉及到软件时,应该有远见并准备好某些场景。大多数开发人员会犯这个错误,客户过一段时间后开始抱怨。软件必须能够处理已知和未知的情况。速度、稳定性、安全性和->统一性比可读性更重要。 - FifthAxiom' '.join(the_string.split(' '))
。这也将删除前导和尾随空格,但将保留换行符、制表符等。 - FifthAxiom与之前的解决方案类似,但更加具体:将两个或多个空格替换为一个:
>>> import re
>>> s = "The fox jumped over the log."
>>> re.sub('\s{2,}', ' ', s)
'The fox jumped over the log.'
我尝试了以下方法,它甚至可以处理极端情况,例如:
str1=' I live on earth '
' '.join(str1.split())
但如果你更喜欢使用正则表达式,它也可以这样写:
re.sub('\s+', ' ', str1)
虽然需要进行一些预处理才能去除末尾和结尾的空格。
str1.strip()
轻松地去除前导和尾随空格,然后将其传递给 re.sub()
函数,如下所示 re.sub(' +', ' ', str1.strip())
。 - Youstanzrimport 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='')
结果:作为代码
"Remove all space:Youcanselectbelowtrimsforremovingwhitespace!!BRAliakbar"
"Remove leading space:You can select below trims for removing white space!! BR Aliakbar"
"Remove trailing spaces: You can select below trims for removing white space!! BR Aliakbar"
"Remove leading and trailing spaces:You can select below trims for removing white space!! BR Aliakbar"
"Remove more than one space: You can select below trims for removing white space!! BR Aliakbar"
一个简单的解决方案
>>> import re
>>> s="The fox jumped over the log."
>>> print re.sub('\s+',' ', s)
The fox jumped over the log.
df['message'] = (df['message'].str.split()).str.join(' ')