2

For example if the string is

s = "##catgiraffeapluscompscI"

How do I get the output to 2 since the first letter that occurs in this string is at position 2 (c)?

I also want this to be able to work for different strings as well (like a function) which may not have c as their first letter, so I don't want

s.find('c')
John Materum
  • 37
  • 1
  • 3

7 Answers7

7

First finding the letter and then its index.

>>> s.find(next(filter(str.isalpha, s)))
2
Kelly Bundy
  • 23,480
  • 7
  • 29
  • 65
  • I don't this answer didn't get much useful clicks. This is for me by far the cleanest code – Christoph Henrici Aug 11 '22 at 11:47
  • this function doesn't handle the error condition where string `s` has no alphabet characters. If you run a string like `+-!` or ` ` or `12345` it will result in a StopIteration error – Nathan Aug 17 '23 at 18:10
  • 1
    @Nathan Yeah, the question doesn't care (otherwise they would've specified what to do), so apparently I didn't either. You can get result `-1` for example by providing `next` with a default letter: `s.find(next(filter(str.isalpha, s), 'a'))` (although that's somewhat ugly). – Kelly Bundy Aug 17 '23 at 18:40
2

You can use a regex to search for the first letter (a-z or A-Z by using the re.I flag), and if found, return the start value from the match object:

import re

def first_letter(s):
    m = re.search(r'[a-z]', s, re.I)
    if m is not None:
        return m.start()
    return -1

s = "##catgiraffeapluscompscI"
i = first_letter(s)
print(i)

Output:

2
Nick
  • 138,499
  • 22
  • 57
  • 95
  • getting this error when using your code Traceback (most recent call last): File "main.py", line 9, in i = first_letter(s) File "main.py", line 2, in first_letter m = re.search(r'[a-z]', s, re.I) NameError: name 're' is not defined  – John Materum Feb 11 '20 at 04:12
  • @JohnMaterum just realised the `import re` in my answer had bad formatting. You need to include that to bring in the regex (`re`) module. See my edit – Nick Feb 11 '20 at 04:13
1

If you don't want to import regex or other modules: the following uses standard library only, will ignore all non-alphabetic characters and give you the position of the first alphabetic character, using the isalpha() method.

foo = "##catgiraffeapluscompscI"

L = len(foo)

vivi = 0
for v in range(1,L):
    if foo[vivi].isalpha():
        print ("First alphabetic character " + foo[vivi] + " at position " + str(vivi))
        break
    vivi = vivi + 1    

Output:

First alphabetic character c at position 2
츄 plus
  • 488
  • 1
  • 7
  • 20
0

You can treat a string as a list of characters, and iterate through it until you find a match. This while statement checks for the character, and if it does not exists it stops you falling off the end of the list.

s = "##catgiraffeapluscompscI"
index = 0
search_char = "c"

while (index != len(s)) and (s[index] != search_char):
    index += 1

if index == len(s):
    print("Character not in string")
else:
    print("Character is at position: ", index)
Parakiwi
  • 591
  • 3
  • 19
0

First, Nick's answer is, I think best. But regexes can be tough, and I'm not good with them, so I tend to stay away from them since in my hands they're pretty fragile.

So for what it's worth, here's a short way that doesn't use regexes:

import string
s = "##catgiraffeapluscompscI"
letters_found = [L for L in string.ascii_letters if L in s]
if letters_found:
    first_letter_position = min([s.find(L) for L in letters_found])
else:
    first_letter_position = -1
print(first_letter_position)

Basically, it makes a list of all the letters in your target (empty if there are none in the target); then for each letter that's present in the target, finds the first location; and takes the smallest of that.

But again, Nick's is better if you're comfortable with regexes.

codingatty
  • 2,026
  • 1
  • 23
  • 32
0

the top answer by kelly bundy only works for a happy path where there *is* a letter in the string. Otherwise next() ends up throwing a StopIteration error. This can simply be caught:

try:
  return s.find(next(filter(str.isalpha, s)))
except StopIteration:
  return -1
Nathan
  • 1,396
  • 3
  • 18
  • 32
-2
def find_index(input_string,input_value):
    return input_string.index(input_value))
answer = find_index("##catgiraffeapluscompscI", 'c')
print(answer)
  • This only works if you already know what the first letter will be. – codingatty Feb 12 '20 at 02:01
  • You can use exception Handling to return None if sub-string is not found. Instead of Using seperate libraries, this is ideal option if you are only concerned with finding sub-string. But if you want to go with some advanced patterns matching based on Theory of Automata, then RE might be the area of concern. – Zeeshan Qureshi Feb 12 '20 at 02:07
  • It's not a matter of handling not-found; it's that it doesn't address the question. This answer returns the first location of the letter 'c'; the OP is asking for the first position of any letter. For example, if s is set to "###snacktime", the correct value is 3 (the position of the 's'); the code posted here will return 6 (the position of the 'c'). – codingatty Feb 12 '20 at 21:45
  • Is it okay now? codingatty. Same logic, OP was supposed to just write that in the body of function. – Zeeshan Qureshi Feb 13 '20 at 07:58
  • No; same problem. You're finding the first 'c', not the first letter. – codingatty Feb 16 '20 at 23:07