【问题标题】:What is the pythonic way to count the leading spaces in a string?计算字符串中前导空格的pythonic方法是什么?
【发布时间】:2012-11-30 16:09:52
【问题描述】:

我知道我可以用这个来计算字符串中的前导空格:

>>> a = "   foo bar baz qua   \n"
>>> print "Leading spaces", len(a) - len(a.lstrip())
Leading spaces 3
>>>

但是有没有更 Pythonic 的方式?

【问题讨论】:

  • 在我看来已经很pythonic了。
  • 不愉快——但不同——方式:a.count(" ", 0, a.index(a.split(None, 1)[0]))
  • 请记住,lstrip 将删除制表符和其他空白字符以及空格。

标签: python


【解决方案1】:

你的方式是pythonic但不正确,它还会计算其他空格字符,只计算空格是明确的a.lstrip(' ')

a = "   \r\t\n\tfoo bar baz qua   \n"
print "Leading spaces", len(a) - len(a.lstrip())
>>> Leading spaces 7
print "Leading spaces", len(a) - len(a.lstrip(' '))
>>> Leading spaces 3

【讨论】:

    【解决方案2】:

    你可以使用itertools.takewhile

    sum( 1 for _ in itertools.takewhile(str.isspace,a) )
    

    并证明它给出的结果与您的代码相同:

    >>> import itertools
    >>> a = "    leading spaces"
    >>> print sum( 1 for _ in itertools.takewhile(str.isspace,a) )
    4
    >>> print "Leading spaces", len(a) - len(a.lstrip())
    Leading spaces 4
    

    我不确定这段代码是否真的比你原来的解决方案更好。它的优点是它不会创建更多的临时字符串,但这非常小(除非字符串真的很大)。我没有发现任何一个版本都可以立即清楚地了解那行代码,所以如果您打算多次使用它(在任何一种情况下都使用适当的 cmets),我肯定会将它包装在一个命名良好的函数中。

    【讨论】:

    • 我试图弄清楚这一点,只是没有 itertools。我真的需要学习itertools...
    • 在我的系统上,(在 Windows 上运行 Python 2.7.10 32 位),lstrip() 的速度是 itertools 的 3.5 倍。
    • @ChaimG -- 我打赌我们可以构造一些不是这种情况的字符串(例如,如果字符串是 真的很长,只有一两个前导空格)。然而,对于许多常见情况,我同意lstrip 会快得多。
    • @mgilson -- 正确。使用字符串:a = ' ' + 'a'*100000000,itertools 快了 67k 倍。我想知道为什么?是因为 lstrip() 创建了字符串的副本吗?
    • @ChaimG -- 这正是为什么:-)。有一次,我假设lstrip() 不会创建新字符串——不变性应该 使这成为可能。然而,我曾经在谷歌邮件列表上发表过这样的声明,并被 Alex Martelli IIRC 更正了 :-)。我不确定他们为什么重复使用旧字符串,但这可能是因为在很多情况下会阻止大字符串被释放。
    【解决方案3】:

    只是为了多样化,理论上你可以使用正则表达式。它比对len() 的双重调用要短一些,而且看起来更好。

    >>> import re
    >>> a = "   foo bar baz qua   \n"
    >>> re.search('\S', a).start() # index of the first non-whitespace char
    3
    

    或者:

    >>> re.search('[^ ]', a).start() # index of the first non-space char
    3
    

    但我不建议这样做;根据我所做的快速测试,它的效率远低于len(a)-len(lstrip(a))

    【讨论】:

      【解决方案4】:

      使用nextenumerate

      next((i for i, c in enumerate(a) if c != ' '), len(a))
      

      对于任何空格:

      next((i for i, c in enumerate(a) if not c.isspace()), len(a))
      

      【讨论】:

        【解决方案5】:

        我最近有一个类似的计算缩进的任务,因此我想将制表符计为四个空格:

        def indent(string: str):
            return sum(4 if char is '\t' else 1 for char in string[:-len(string.lstrip())])
        

        【讨论】:

          【解决方案6】:

          这看起来……对我来说很棒。通常我会回答“是 X Pythonic 吗?”有一些功能魔法的问题,但我觉得这种方法不适合字符串操作。

          如果有一个内置的 only 返回前导空格,并采用 len() ,我会说去吧 - 但 AFAIK 没有,并且re 和其他解决方案绝对是矫枉过正。

          【讨论】:

            【解决方案7】:

            你可以使用正则表达式:

            def count_leading_space(s): 
                match = re.search(r"^\s*", s) 
                return 0 if not match else match.end()
            
            In [17]: count_leading_space("    asd fjk gl")                                  
            Out[17]: 4
            
            In [18]: count_leading_space(" asd fjk gl")                                     
            Out[18]: 1
            
            In [19]: count_leading_space("asd fjk gl")                                      
            Out[19]: 0
            
            

            【讨论】:

              猜你喜欢
              • 2014-02-20
              • 1970-01-01
              • 2019-10-29
              • 2014-05-22
              • 1970-01-01
              • 2014-01-19
              • 2020-10-30
              • 2010-12-17
              • 1970-01-01
              相关资源
              最近更新 更多