How to index list when there is 2 of the same char

Viewed 48

I have been trying to make the even letters in a string become upper-cased and the odd letters to become lower-cased with a function, like so:

def myfunc('apple'):
    #OUTPUTS: 'ApPlE'

This is what I made:

def myfunc(mystring):
    stringList = [letter for letter in mystring]
    for letter in stringList[1::2]:
        stringList[stringList.index(letter)] = letter.lower()
    for letter in stringList[::2]:
        stringList[stringList.index(letter)] = letter.upper()
    return ''.join(stringList)

I believe that, when I use words like 'apple' where there is two identical letters, the index() function can only manage to give me the index of the first 'p', if my word is apple. It returns:

'APplE'

How could I fix this?

2 Answers

By iterating over the indices of the string, using the built-in function enumerate, together with the characters of the string (strings are also iterable):

def myfunc(mystring):
    out = []
    for i, c in enumerate(mystring):
        if i % 2 == 0:
            out.append(c.upper())
        else:
            out.append(c.lower())
    return "".join(out)

Example output:

>>> myfunc('apple')
'ApPlE'

This is also a lot more efficient, since it only iterates over the string once. Your code iterates many times (each stringList.index call does a linear search for the letter).

If you want to make it a bit harder to read but re-use a bit more of what you already have, you can also use this, but I would not recommend it (as it iterates three times over the string, once to build the list and then twice to replace the characters):

def myfunc(mystring):
    stringList = list(mystring)
    stringList[::2] = map(str.upper, stringList[::2])
    stringList[1::2] = map(str.lower, stringList[1::2])
    return "".join(stringList)

The method list.index returns the index of the first occurence, making it unfit for recovering the index of the current element. Instead, you should use enumerate, this will allow you to get the expected result with a single list-comprehension.

def myFunc(s):
    return ''.join([c.lower() if i % 2 else c.upper() for i, c in enumerate(s)])

print(myFunc('apple')) # ApPlE
Related