该函数的参数满足以下规则:
目标:删除交错的重复空格&剥离尾随空格。
这就是我现在这样做的方式:
# toks - a priori no leading space
def squeeze(toks):
import re
p = re.compile(r'\W+')
a = p.split( toks )
for i in range(0, len(a)):
if len(a[i]) == 0:
del a[i]
return ' '.join(a)
>>> toks( ' Mary Decker is hot ' )
Mary Decker is hot
这可以改善吗? Pythonic够吗?
答案 0 :(得分:9)
我就是这样做的:
" ".join(toks.split())
PS。这个问题中是否存在潜意识信息? ; - )
答案 1 :(得分:4)
你不能使用rstrip()吗?
some_string.rstrip()
用于从两侧剥离弦的或strip()?
另外:strip()方法也支持传递任意条形字符:
string.strip = strip(s, chars=None)
strip(s [,chars]) -> string
相关:如果你需要在中间删除空格:拆分字符串,删除条款并重新加入它。
阅读API有帮助!
答案 2 :(得分:2)
按字面意思回答你的问题:
是的,可以改进。第一个改进是使其发挥作用。
>>> squeeze('x ! y')
'x y' # oops
问题1:当您使用\ s +(空格字符)时,您正在使用\ W +(非单词字符)
>>> toks = 'x ! y z '
>>> re.split('\W+', toks)
['x', 'y', 'z', '']
>>> re.split('\s+', toks)
['x', '!', 'y', 'z', '']
问题2:删除空字符串的循环有效,但只是偶然。如果你想要一个通用循环来原位删除空字符串,你需要向后工作,否则你的下标我将从剩余的元素数量中解脱出来。它在这里工作,因为没有捕获组的re.split()只能在开始和结束时生成空元素。您已经定义了启动问题,并且结束案例不会导致问题,因为之前没有删除。所以你留下了一个非常丑陋的循环,可以用两行代替:
if a and not a[-1]: # guard against empty list
del a[-1]
但是除非你的字符串很长并且你担心速度(在这种情况下你可能不应该使用re),你可能想要允许引导空格(断言如“我的数据没有领先的空白“按惯例被忽略”,并且只是在一个循环中实现它:
a = [x for x in p.split(toks) if x]
下一步是避免构建列表a
:
return ' '.join(x for x in p.split(toks) if x)
现在你确实提到了“Pythonic”......所以让我们抛弃所有重新导入和编译开销的东西,以及genxp,然后就这样做:
return ' '.join(toks.split())
答案 3 :(得分:1)
好吧,如果我能合理地完成工作,我倾向于不使用re
模块
内置的功能和特性。例如:
def toks(s):
return ' '.join([x for x in s.split(' ') if x])
...似乎只使用内置split
,join
和列表推导来完成相同的目标,以过滤拆分字符串的空元素。
那更像是“Pythonic吗?”我认同。但是我的意见几乎没有权威性。
这也可以作为lambda表达式完成;而且我认为这不会是Pythonic。
顺便提一下,假设您只想挤出重复的空格并修剪前导和尾随空格。如果您的意图是将所有空白序列组合成单个空格(并修剪前导和尾随),则将s.split(' ')
更改为s.split()
- 不将任何参数或None
传递给{{1}方法与传递空格不同。
答案 4 :(得分:0)
为了使你的代码更像Pythonic,你必须意识到在Python中, a [i] 是一个字符串,而不是deleting a[i] if a[i]==''
,它更好keeping a[i] if a[i]!=''
。
所以,而不是
def squeeze(toks):
import re
p = re.compile(r'\W+')
a = p.split( toks )
for i in range(0, len(a)):
if len(a[i]) == 0:
del a[i]
return ' '.join(a)
写
def squeeze(toks):
import re
p = re.compile(r'\W+')
a = p.split( toks )
a = [x for x in a if x]
return ' '.join(a)
然后
def squeeze(toks):
import re
p = re.compile(r'\W+')
return ' '.join([x for x in p.split( toks ) if x])
然后,考虑到函数可以接收生成器以及列表:
def squeeze(toks):
import re
p = re.compile(r'\W+')
return ' '.join((x for x in p.split( toks ) if x))
并且加倍括号不是强制性的:
def squeeze(toks):
import re
p = re.compile(r'\W+')
return ' '.join(x for x in p.split( toks ) if x)
此外,每次调用函数时,都不要求Python验证函数 squeeze()的命名空间中是否存在re
(它就是它的作用) ),最好通过defautlt传递re
作为参数:
import re
def squeeze(toks,re = re):
p = re.compile(r'\W+')
return ' '.join(x for x in p.split( toks ) if x)
,甚至更好:
import re
def squeeze(toks,p = re.compile(r'\W+')):
return ' '.join(x for x in p.split( toks ) if x)
。
备注:表达式中的if x
部分仅用于在标记开始和结束时将标题''
和结尾''
分开列表p.split( toks )
有空格。
但是,不是分裂,而是保持所需的一切是好的:
import re
def squeeze(toks,p = re.compile(r'\w+')):
return ' '.join(p.findall(toks))
所有这一切,你的问题中的模式r'\W+'
对你的目的是错误的,就像John Machin指出的那样。
如果要压缩内部空格并删除尾随空格,则纯粹意义上的空格指定字符集' ' , '\f' , '\n' , '\r' , '\t' , '\v'
(请参阅re中的\ s),您必须替换您的分裂用这个:
import re
def squeeze(toks,p = re.compile(r'\s+')):
return ' '.join(x for x in p.split( toks ) if x)
或者,保持正确的子串:
import re
def squeeze(toks,p = re.compile(r'\S+')):
return ' '.join(p.findall(toks))
这只是更简单,更快速的表达式' '.join(toks.split())
但是,如果您实际上只想压缩内部并删除尾随字符' '
和'\t'
,保持新行不变,您将使用
import re
def squeeze(toks,p = re.compile(r'[^ \t]+')):
return ' '.join(p.findall(toks))
并且不能被其他任何东西取代。
答案 5 :(得分:0)
我知道这个问题已经过时了。但为什么不使用正则表达式?
import re
result = ' Mary Decker is hot '
print(f"=={result}==")
result = re.sub('\s+$', '', result)
print(f"=={result}==")
result = re.sub('^\s+', '', result)
print(f"=={result}==")
result = re.sub('\s+', ' ', result)
print(f"=={result}==")
输出
== Mary Decker is hot ==
== Mary Decker is hot==
==Mary Decker is hot==
==Mary Decker is hot==