【问题标题】:Returning the lowest index for the first non whitespace character in a string in Python返回Python中字符串中第一个非空白字符的最低索引
【发布时间】:2011-01-23 15:38:34
【问题描述】:

在 Python 中执行此操作的最短方法是什么?

string = "   xyz"

必须返回 index = 3

【问题讨论】:

标签: python string string-matching


【解决方案1】:

许多以前的解决方案在他们提出的解决方案中的几个点上进行了迭代。有些人会复制数据(字符串)。 re.match()、strip()、enumerate()、isspace() 在幕后重复工作。

next(idx for idx, chr in enumerate(string) if not chr.isspace())
next(idx for idx, chr in enumerate(string) if not chr.whitespace)

是针对各种前导空白类型(例如垂直制表符等)测试字符串的不错选择,但这也会增加成本。

但是,如果您的字符串仅使用空格字符或制表符,那么以下更基本的解决方案、清晰快速的解决方案也使用更少的内存。

def get_indent(astr):

    """Return index of first non-space character of a sequence else False."""

    try:
        iter(astr)
    except:
        raise

    # OR for not raising exceptions at all
    # if hasattr(astr,'__getitem__): return False

    idx = 0
    while idx < len(astr) and astr[idx] == ' ':
        idx += 1
    if astr[0] <> ' ':
        return False
    return idx

虽然这在视觉上可能不是绝对最快或最简单的,但此解决方案的一些好处是您可以轻松地将其转移到其他语言和 Python 版本。并且可能是最容易调试的,因为几乎没有什么神奇的行为。如果您将函数的内容与代码内联而不是放在函数中,您将删除函数调用部分,并使此解决方案在字节码中与其他解决方案相似。

此外,此解决方案允许更多变体。比如给标签加个测试

or astr[idx] == '\t':

或者您可以将整个数据测试为可迭代一次,而不是检查每一行是否可迭代。记住像 ""[0] 会引发异常,而 ""[0:] 不会。

如果你想将解决方案推送到内联,你可以走非 Pythonic 路线:

i = 0
while i < len(s) and s[i] == ' ': i += 1

print i
3

。 .

【讨论】:

    【解决方案2】:
    import re
    def prefix_length(s):
       m = re.match('(\s+)', s)
       if m:
          return len(m.group(0))
       return 0
    

    【讨论】:

    • """确保你的代码优雅地“什么都不做”。"""——归功于 Jon Bentley IIRC。
    • 原谅我的无知,但他是谁?
    • 无知是可以原谅的;不愿意使用搜索引擎是另一回事;-) en.wikipedia.org/wiki/Jon_Bentley
    • @JohnMachin - D'oh...关于+而不是*的好点。今天早上我的思维能力还没有完全发挥出来。
    • 还有多余的括号。
    【解决方案3】:

    看起来“正则表达式可以做任何事情”团队已经休息了一天,所以我会填写:

    >>> tests = [u'foo', u' foo', u'\xA0foo']
    >>> import re
    >>> for test in tests:
    ...     print len(re.match(r"\s*", test, re.UNICODE).group(0))
    ...
    0
    1
    1
    >>>
    

    FWIW:花费的时间是 O(the_answer),而不是 O(len(input_string))

    【讨论】:

      【解决方案4】:
      >>> string = "   xyz"
      >>> map(str.isspace,string).index(False)
      3
      

      【讨论】:

      • -1 因为它对任何全空白字符串都失败了... :( "ValueError: False is not in list"
      【解决方案5】:
      >>> string = "   xyz"
      >>> next(idx for idx, chr in enumerate(string) if not chr.isspace())
      3
      

      【讨论】:

      • -1 因为它对于任何全空白字符串都失败了... "StopIteration:" 在这种情况下会输出错误
      【解决方案6】:
      >>> s = "   xyz"
      >>> len(s) - len(s.lstrip())
      3
      

      【讨论】:

      • 如果 s 很长并且空白前缀很短,其他解决方案(不制作 s 的临时副本的解决方案,获取其长度,然后将临时对象丢弃)可能是更可取。
      • @JohnMachin 字符串在 Python 中是不可变的,所以我非常怀疑解释器会为strip() 复制一份。原始字符串可以简单地重复使用不同的起始位置。
      【解决方案7】:
      >>> next(i for i, j in enumerate('   xyz') if j.strip())
      3
      

      >>> next(i for i, j in enumerate('   xyz') if j not in string.whitespace)
      3
      

      在 Python

      (...).next()
      

      【讨论】:

      • blah.strip()blah.isspace() 使用 Unicode 可以正常工作; string.whitespace 在上个世纪被冻结了。
      • @John:说谁?我认为string.whitespace 是仅次于公认的第二个最有效的方法。
      • 重新阅读我的评论。我说的是使用 Unicode;没有提到效率。
      猜你喜欢
      • 2017-09-21
      • 1970-01-01
      • 2014-10-26
      • 1970-01-01
      • 1970-01-01
      • 2013-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多