Replace 2nd occurrence of letter

Viewed 201

I'm new to python and I'm trying to create a code for a course where I have to replace the second occurrence of each letter with something else such as:

print(vowel_swapper("aAa eEe iIi oOo uUu")) Should print "a/\a e3e i!i o000o u/u" to the console

The code works for this string but when I do the second:

print(vowel_swapper("Hello World")) Should print "Hello Wooorld" to the console

it outputs "Hell000 W000rld". I'm sure that the way I'm doing it won't be very efficient, since I'm new to it I'm not expecting it to be efficient I'm just trying to learn how to make it do what I want it to do.

def vowel_swapper(string):

    replace1 = ["a", "A"]
    replace2 = ["e", "E"]
    replace3 = ["i", "I"]
    replace4 = ["o", "O"]
    replace5 = ["u", "U"]
    new_string = string

    count = 0
    for i in range(0, len(string)):
        if (string[i] == replace1[0]) or (string[i] == replace1[1]):
            count = count + 1
            if count == 2:
                new_string = new_string.replace(string[i], '/\\')

    count = 0
    for i in range(0, len(string)):
        if (string[i] == replace2[0]) or (string[i] == replace2[1]):
            count = count + 1
            if count == 2:
                new_string = new_string.replace(string[i], "3")

    count = 0
    for i in range(0, len(string)):
        if (string[i] == replace3[0]) or (string[i] == replace3[1]):
            count = count + 1
            if count == 2:
                new_string = new_string.replace(string[i], "!")

    count = 0
    for i in range(0, len(string)):
        if (string[i] == replace4[0]) or (string[i] == replace4[1]):
            count = count + 1
            if count == 2:
                new_string = new_string.replace(string[i], "000")

    count = 0
    for i in range(0, len(string)):
        if (string[i] == replace5[0]) or (string[i] == replace5[1]):
            count = count + 1
            if count == 2:
                new_string = new_string.replace(string[i], "\\/")

    return new_string
2 Answers

You should enumerate the string to easily get the index of the second occurrence of the vowel you are looking for, then you can replace it using the join function to join the substring before the replaced character and the substring after it.

The following code has two key advantages:

  1. By accepting as a parameter a dictionary (swaps) with all the char : replacement pairs you can replace all the characters you want, not just the vowels.
  2. Since it is index based, you can easily change the occurrence index (idx) and replace the third, the forth occurrence ... and so on... I set its default value to 1 to directly replace the 2nd occurrence if you do not provide a value.

Code:

def chars_swapper(s, swaps, idx=1):
    
    for k, v in swaps.items():
        l = [i for i, char in enumerate(s) if char.upper() == k]
        if len(l) > idx:  s = v.join((s[:l[idx]], s[l[idx]+1:]))
            
    return s

Output:

SWAPS = {'A':'/\\', 'E':'3', 'I':'!', 'O':'000', 'U': '/'}

chars_swapper("aAa eEe iIi oOo uUu", SWAPS)
'a/\\a e3e i!i o000o u/u'

chars_swapper("Hello World", SWAPS)
'Hello W000rld'

One Backslash:

In Python strings, the backslash "\" is a special character, also called the "escape" character. It is used in representing certain whitespace characters: "\\" is a backslash, "\t" is a tab, "\n" is a newline, and "\r" is a carriage return. Conversely, prefixing a special character with "\" turns it into an ordinary character.

print(chars_swapper("aAa eEe iIi oOo uUu", SWAPS))
a/\a e3e i!i o000o u/u

You can read more about it here (2.4.1. String and Bytes literals): Python docs

Here's my solution:

>>> SWAPS = {
        "A": "/\\", "E": "3", "I": "!", "O": "000", "U": "/"
    }
>>> def vowel_swapper(string, swaps=SWAPS):
        searching = {
            "A": False, "E": False, "I": False, "O": False, "U": False
        }
        str_list = list(string)
        for i, char in enumerate(str_list):
            char = char.upper()
            if searching.get(char) is False:
                searching[char] = True
            elif searching.get(char):
                str_list[i] = SWAPS.get(char)
                del searching[char]
        return "".join(str_list)

>>> vowel_swapper("aAa eEe iIi oOo uUu")
'a/\\a e3e i!i o000o u/u'
>>> vowel_swapper("Hello World")
'Hello W000rld'
>>> 

The dictionary searching determines whether the function is actively searching for a letter to replace. Once the first instance of a vowel is found, the value which corresponds to the vowel is set from False to True. If another instance of the same vowel is found (when the corresponding value in searching is True), the vowel is replaced, according to swaps, and the key is deleted from searching (to avoid repeats).

By iterating over string as a list, we can use index assignment (strings are not mutable; lists are). Then, at the end, the str.join() method is called to return the list of strings as a single string.


Edit

From the comments, I understand that OP wants to view the string with only one backslash, as opposed to the escaped backslash used in Python. To do so, you can write the resultant string to a file, then view the file:

>>> with open("file.txt", "w") as file:
        file.write(vowel_swapper("aAa eEe iIi oOo uUu"))

If you then open up the file, you'll see the backslash without the escape character:

a/\a e3e i!i o000o u/u

file.txt

Related