什么是从字符串中删除尾随空格的pythonic方法?

时间:2011-05-04 05:34:51

标签: python

该函数的参数满足以下规则:

  1. 它没有任何领先的空白
  2. 它可能有尾随空格
  3. 字符串中可能存在交错的空格。
  4. 目标:删除交错的重复空格&剥离尾随空格。

    这就是我现在这样做的方式:

    # 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够吗?

6 个答案:

答案 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])

...似乎只使用内置splitjoin和列表推导来完成相同的目标,以过滤拆分字符串的空元素。

那更像是“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==