如何在Python中查找字符串中第一个非空格字符的索引?

8
Scenario:
情境:
>>> a='   Hello world'
index = 3

在这种情况下,“H”索引是3。但我需要一种更通用的方法,对于任何字符串变量“a”,我都需要知道第一个字符的索引?
另一种情况:
>>> a='\tHello world'
index = 1

4
了解,空格在技术上也算是字符。 - Matt Ball
你的第二个例子应该是 1,对吧? - kirelagin
在这种情况下,lstrip为什么不起作用? - mgilson
如果字符串为空或全部为空格,您想要什么? - dansalmo
5个回答

8
如果您指的是第一个非空格字符,我会使用类似以下的代码...
>>> a='   Hello world'
>>> len(a) - len(a.lstrip())
3

还有一个有点有趣的例子:

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

但我敢打赌第一个版本更快,因为它本质上就是在C语言中实现了这个循环 -- 当然,它在完成后需要构建一个新字符串,但这几乎不需要代价。


为了完整起见,如果字符串为空或完全由空格组成,则这两种情况都会返回len(a)(如果您尝试使用它进行索引,则无效...)

>>> a = "foobar"
>>> a[len(a)]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: string index out of range

我已经完成了这个任务,如果左侧字符是空格,它可以正常工作。但是如果变量为'a=/tHello World',那么lstrip就无法起作用了。 - Kaushik
我需要一种更通用的方法。 - Kaushik
2
@karthik,你应该在问题中说明这一点。请参考另一个答案。 - kirelagin
@karthik -- 对于 a='\tHello World',为什么这个方法不起作用呢?它应该会返回 1 - mgilson
@mgilson 您是对的,我的错。它会起作用的。我做了错误的计算 :) - Kaushik
@downvoter -- 如果您能解释一下为什么您认为这个答案不够好,我很乐意尝试改进它。 - mgilson

3

使用 正则表达式

>>> import re
>>> a='   Hello world'
>>> re.search(r'\S',a).start()
3
>>> a='\tHello world'
>>> re.search(r'\S',a).start()
1
>>>

处理字符串为空或只包含空格的情况的函数:

>>> def func(strs):
...     match = re.search(r'\S',strs)
...     if match:
...         return match.start()
...     else:
...         return 'No character found!'
...     
>>> func('\t\tfoo')
2
>>> func('   foo')
3
>>> func('     ')
'No character found!'
>>> func('')
'No character found!'

@kirelagin \S 相对于 \w 有什么优势吗? - Ashwini Chaudhary
1
@AshwiniChaudhary -- 你可以传递一个字符串,例如 ' .foo'\w 会忽略 . - mgilson
当字符串为空或只包含空格时,会出现“AttributeError: 'NoneType' object has no attribute 'start'”错误。 - dansalmo
@dansalmo 是的,但可以轻松使用if-else或try-except块来处理。 - Ashwini Chaudhary
@downvoter请解释一下你的负评,这样我就可以改进我的回答。 - Ashwini Chaudhary

2

您也可以尝试:

a = '   Hello world'
a.index(a.lstrip()[0])
=> 3

只要字符串中至少包含一个非空字符,这个方法就会起作用。我们可以更加谨慎,在此之前进行检查:
a = '    '
-1 if not a or a.isspace() else a.index(a.lstrip()[0])
=> -1

说实话,我宁愿得到异常,因为-1是一个完全可以接受的索引,但这只是我的个人偏好。 - mgilson
@dansalmo 这个方法行不通:a.index(a.lstrip()[0:]) 对于像 ' ' 这样的字符串会返回 0,这是不正确的。 - Óscar López
@mgilson 这取决于约定,如果我们只允许返回的索引 >= 0,那就没问题。 - Óscar López
@dansalmo 这个更短,但需要创建一个额外的字符串。我还是坚持我的 :) - Óscar López
@mgilson 我想我是一个 LBYL 类型的人 :) - Óscar López
显示剩余3条评论

1

另一种方法,只是为了好玩...使用特殊函数!

>>> def first_non_space_index(s):
    for idx, c in enumerate(s):
        if not c.isspace():
            return idx


>>> a = '   Hello world'        
>>> first_non_space_index(a)
3

2
也许将其重命名为 first_non_space_index ... 你现在的名称让人觉得你会返回 'H' - mgilson
也许你应该处理整个字符串都是空格的情况。在这种情况下,你应该返回 None。我建议在循环后使用 return len(s) - Fabian
默认情况下,所有函数都返回 None。因此,如果找不到索引,那么无论如何都会返回 None。 - Inbar Rose

0
根据mgilson的回答,您可以使用lstrip来去除任何您想要的字符 -
unwanted = ':!@#$%^&*()_+ \t\n'
a= '  _Hello world'
res = len(a) - len(a.lstrip(unwanted)) 

它确实可以,但是我认为从karthik的评论中,他想要一个更通用的方法(看起来他最终并不需要了)。 - Ariel
我的意思是,你所拥有的比一个简单的 lstrip() 不够通用(可能稍微不那么高效),因为 Python 对 lstrip()lstrip(argument) 使用了不同的算法。 - mgilson
你是正确的。我已编辑了我的回答,这样它至少会提供更多的功能。 - Ariel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接