-7

I'm very new to python and have been trying out codewars. Some problems pretty difficult for me. What I'm trying to accomplish is,"to know the index of the vowels in a given word, for example, there are two vowels in the word super (the second and fourth letters)." I don't really understand how to use index and/or find. I need to know I can edit this code to find the positions of the vowels in any given word.

def vowel_indices(word):
    word.index("a","i","o","u","e","y")
    word.find("a","i","o","u","e","y")
  • 1
    This code does not run. What do you expect it to do (print, return)? – handle Jun 24 '16 at 14:08
  • I was trying to get it to return the position of the vowels. I know it's not complete I just am confused about what to do next. – Riccardi Dalexis Jun 24 '16 at 15:15
  • 1
    Yes, but your code would produce error messages. You don't state those messages or ask about them. They give much more information than "wrong" to help you solve your problem. You use the functions incorrectly. The documentation tells you exactly what the do and how to use them. They just take one argument to look for in `word`. You do not use their output. See my answer and please accept it.. – handle Jun 24 '16 at 15:25
  • Never mind, PM 2Ring's later solution is the fastest. – handle Jun 24 '16 at 15:58
  • Ok thanks. I will try to post better questions. – Riccardi Dalexis Jun 25 '16 at 13:45

3 Answers3

4

You don't call str.find or str.index like that. They both take arguments of the form

(sub[, start[, end]])

which means they take a single substring to search for, possibly followed by a start index to specify where in the target string to start searching from, possibly followed by an (exclusive) end index to specify where to stop searching.

However, this isn't really a job for .find or .index. Both of those methods have to do a linear scan over the string they search, and to find all vowels you have to loop over all the vowels, so you effectively have a double loop.

Fortunately, Python provides a more efficient way: put the vowels into a set and then loop over the letters in the word and test if each letter is in the vowel set. Testing set membership is very efficient and it doesn't involve a linear scan over the set. To catch all vowels we need to put both the upper-case & lower-case vowels into our set. To keep track of the position of each vowel in the word we can use the enumerate function.

vowels = set("AEIOUYaeiouy")
def vowel_indices(word):
    return [i for i, c in enumerate(word) if c in vowels]

# Test
for word in ("super", "AMAZING"):
    print(word, vowel_indices(word))

output

super [1, 3]
AMAZING [0, 2, 4]
PM 2Ring
  • 54,345
  • 6
  • 82
  • 182
  • Using `set` instead of string seems about 10% faster (function renamed and used with [timeit](https://docs.python.org/3/library/timeit.html#examples) like `print(timeit.timeit("test('Banana!')", setup="from __main__ import test"))` – handle Jun 24 '16 at 15:48
1

str.index:

Like S.find() but raise ValueError when the substring is not found.

To find the vowels in a given word you need to take one note as you already mentioned in your question, some words can have more than one vowel (i.e.,"enumerate"), so this is one way to deal with them:

def vowel_indices(word):
    v = ["a","e","u",...]
    for index, letter in enumerate(word):
        if letter in v:
           print("Vowel letter %s, index of [%s]" % (letter, index))

Also refer to the documentation Common string operations

Examples for string find in Python

Python String index() Method

How to get the position of a character in Python?

Community
  • 1
  • 1
GIZ
  • 4,409
  • 1
  • 24
  • 43
  • 1
    The `in` test also works on a string `if letter in "aeiouy":`, but it would be a little faster to test against a set of vowels. – PM 2Ring Jun 24 '16 at 14:58
0

Check the documentation

Build your code around the method:

# characters to look for in a list (string would work as well)
vowels = ["a","i","o","u","e","y"]

# a function (method)
def vowel_indices(word):
    # prepare empty list to collect the positions in
    hits = []

    # test every of your vowels
    for vowel in vowels:
        # the function returns the index of vowel in word or -1 if it's not there
        pos = word.find(vowel)
        
        # test for match
        if pos>0:
            # collect match in list
            hits.append( pos )

    # done, return the list
    return hits

# the string to analyse
word = "super"

# pass the string to the method and get its return value
results = vowel_indices(word)

# output the return value 
print(results)

Output:

[1, 3]

This is really a list object, but Python prints its elements.


As pointed out by @PM 2Ring, this only finds the first occurence of the vowel in the string. This is for two reasons:

  1. Each vowel is only tested once

  2. str.find() only finds the leftmost match (see also rfind()):

    Return the lowest index in the string where substring sub is found within the slice s[start:end].

So I pointlessly complicated the code as follows to make it work:

# characters to look for in a list (string would work as well)
vowels = ["a","i","o","u","e","y"]

# a function (method)
def vowel_indices(word):
    # prepare empty list to collect the positions in
    hits = []
    # test every of your vowels
    for vowel in vowels:
        # work on a copy
        temp = word
        # look first, give up later
        while True:
            # the function returns the index of vowel in word or -1 if it's not there
            pos = temp.lower().find(vowel)
            # test for match
            if pos>0:
                # collect match in list
                hits.append( pos )
                # remove matched vowel from
                temp = temp[:pos] + " " + temp[pos+1:]
                print(temp)
            else:
                break

    # done, return the list
    return hits

# the string to analyse
word = "Banana!"

# pass the string to the method and get its return value
results = vowel_indices(word)

# output the return value
print(results)

Output

B nana!
B n na!
B n n !
[1, 3, 5]
Community
  • 1
  • 1
handle
  • 5,859
  • 3
  • 54
  • 82
  • Yes, but easy to understand. However I failed to account for uppercase, so it should use `word.lower().find(vowel)` – handle Jun 24 '16 at 15:38
  • On second thoughts, this doesn't work properly if the word contains multiples of the same vowel: it will only find the first occurrence of each vowel. – PM 2Ring Jun 24 '16 at 16:05
  • There, I fixed it! – handle Jun 24 '16 at 17:10