4

I'd like to count the number of leading spaces in a string.What's the most Pythonic way of doing this?

>>>F(' ' * 5 + 'a')
5

(update) Here are timings of several of the answers:

import timeit
>>> timeit.timeit("s.index(re.search(r'\S',s).group())", number=10000, setup="import re;s='     a'")
0.027384042739868164
>>> timeit.timeit("len([i for i in itertools.takewhile(str.isspace,s)])", number=10000, setup="import itertools;s='     a'")
0.025166034698486328
>>> timeit.timeit("next(idx for idx,val in enumerate(s) if val != ' ')", number=10000, setup="s='     a'")
0.028306961059570312
>>> timeit.timeit("F('     a')", number=10000, setup="def F(s): return len(s)-len(s.lstrip(' '))")
0.0051808357238769531
Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
Mark Harrison
  • 297,451
  • 125
  • 333
  • 465
  • @AvinashRaj He is counting the leading spaces – Bhargav Rao Apr 12 '15 at 06:55
  • I think YOU's answer is the most Pythonic, with Saksham Varma's coming a close second; YMMV. I guess it'd be nice to run some timeit tests on the various alternatives proposed... BTW, using an upper-case letter like`F` for a function name is definitely _not_ Pythonic. :) – PM 2Ring Apr 12 '15 at 07:34

10 Answers10

7

Using re module

>>> s
'     a'
>>> import re
>>> s.index(re.search(r'\S',s).group())
5

Using itertools

>>> import itertools
>>> len([i for i in itertools.takewhile(str.isspace,s)])
5

The brute force way

>>> def F(s):
...     for i in s:
...          if i!=' ':
...               return s.index(i)
... 
>>> F(s)
5
Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
4
>>> F = lambda x:len(x)-len(x.lstrip(' '))
>>> F(' ' * 5 + 'a')
5

If you need to find length of leading whitespaces, you can just remove ' ' from lstrip, which is now limited to spaces only

YOU
  • 120,166
  • 34
  • 186
  • 219
3
def f(string):
    try:
        return [c == ' ' for c in string].index(False)
    except ValueError:
        return -1

looks for the first character that doesn't match ' '

Huey
  • 5,110
  • 6
  • 32
  • 44
  • 1
    Nice. `except ValueError:` is much better than using an unnamed except clause. From https://docs.python.org/3/tutorial/errors.html#handling-exceptions "The last except clause may omit the exception name(s), to serve as a wildcard. Use this with extreme caution, since it is easy to mask a real programming error in this way!". Also see http://stackoverflow.com/questions/14797375/should-i-always-specify-an-exception-type-in-except-statements – PM 2Ring Apr 12 '15 at 07:21
3

Use enumerate to iterate through the string s. As soon as you hit a non ' ' item in s, print that index, which is what you are looking for.

>>> for i, val in enumerate(s):
...    if val != ' ':  
...       print i  
...       break
...
5
Saksham Varma
  • 2,122
  • 13
  • 15
1

Through re module. and using len function.

>>> s = '     a'
>>> len(re.sub(r'\S.*', '',s))
5

This would remove all the chars from the first non-space character upto the last. Then the len function applies on the resultant string giving you the length of leading spaces.

OR

>>> s = '     a'
>>> len(re.match(r'\s*', s).group())
5
>>> s = 'a'
>>> len(re.match(r'\s*', s).group())
0

This would match only zero or more leading spaces.

OR

Use re.match function's end() attribute.

>>> s = '     a'
>>> re.match(r'\s*', s).end()
5
>>> re.match(r'\s*', 'd').end()
0

Thanks to Adam

Community
  • 1
  • 1
Avinash Raj
  • 172,303
  • 28
  • 230
  • 274
1

Ooh one more that no one has posted yet.

def leading_spaces(s):
    return next(idx for idx,val in enumerate(s) if val != " ")

This is almost certainly the fastest way to do it

Adam Smith
  • 52,157
  • 12
  • 73
  • 112
0

A simple map and then sum:

>>> sum(map(bool, takewhile(str.isspace, '    a  ')))
4
Burhan Khalid
  • 169,990
  • 18
  • 245
  • 284
0

Code:

>>> i = 0
>>> while i < len(s):
...     if s[i] != ' ':
...       print i
...       break  
...     i += 1

5
neo
  • 33
  • 1
  • 5
0

Strip the string on the left side using the first character:

>>> s = 'aaaaabaca'
>>> len(s) - len(s.lstrip(s[0]))
5

If you want to make it work for empty strings, simply add a check:

>>> s = ''
>>> len(s) - len(s.lstrip(s[0])) if s else 0
0
wouter bolsterlee
  • 3,879
  • 22
  • 30
-2

sorry for not being explicit enough....initialize a counter...you just iterate through the string and set a condition to check if each variable in the list a whitespace and the counter increment by 1...

counter = 0

sstring = " " * 5 + "a"

for x in sstring:

    if x == " ":
        counter += 1
    else:
        continue

print(counter)

i am sincerely sorry i dont know why my script keeps showing in this lousy format..i am kind of new here

samlexxy
  • 115
  • 1
  • 1
  • 8
  • Could you please add some more details to your answer? – abarisone Apr 12 '15 at 06:49
  • 1
    @samlexxy you will need to break in the else block. Try running this for a string like `f = " " * 5 + "a " + " b"`, and you will see. – Anshul Goyal Apr 12 '15 at 07:09
  • im iterating through the string..once the iteration is done the program breaks it self automatically....perhaps maybe i comprehend your explanation – samlexxy Apr 12 '15 at 07:13
  • 2
    This code doesn't work. You should be testing `if x == " ":`, **not** `f == " "`. But even then it counts _all_ spaces in `f`, not just _leading_ spaces. And to fix that you need to change `continue` to `break`, as mu 無 explained. – PM 2Ring Apr 12 '15 at 07:29
  • sorry...lemme try running the code using my interpreter – samlexxy Apr 12 '15 at 07:41
  • It's _always_ a good idea to test code before posting it as an answer, just in case you accidentally make a simple mistake in syntax &/or logic. – PM 2Ring Apr 12 '15 at 07:48
  • You _still_ didn't fix the continue -> break stuff. Also, your test data is inadequate. – PM 2Ring Apr 12 '15 at 08:04
  • i guess you are new to python right and you dont know the difference between "continue" and "break" statatement....read the question one more time....a script to count the numbers of white space at the beginning of a string.....you can also omit the "else: continue" statement if you dont understand it. – samlexxy Apr 12 '15 at 08:22
  • I'm _not_ new to Python. Try your code with `sstring = ' a bc '`. It prints `3`, it should print `1`, as there's only one leading space in that string. – PM 2Ring Apr 12 '15 at 08:29
  • dude i complete the code the guy asked..which was the first 5 whitespace....with your example i believe the continue should be "break" like you should....nd like i said mai program was the writer's example dependent not universal – samlexxy Apr 12 '15 at 08:36
  • 1
    Your code doesn't find the leading whitespace in a string, it finds the total number of whitespace in a string, which is easier to do as `sum(ch.isspace() for ch in s)`. – Adam Smith Apr 12 '15 at 09:02
  • right that was the motive.....i could edit it tho.....it would only take little modification – samlexxy Apr 13 '15 at 01:56