2

I've been playing around with encoding random sets of strings using a dictionary. I've gotten my code to replace the letters I want, but in some cases it will replace a character more than once, when I truly only want it to replace the letter in the string once. This is what I have:

def encode(msg,code):
    for i in msg:
        for i in code:
            msg = msg.replace(i, code[i])
        return msg

for testing purposes I used the function calls: initial:

encode("blagh", {"a":"e","h":"r"})

and a more complex string:

encode("once upon a time",{'a':'ae','e':'ei','i':'io','o':'ou','u':'ua'})

for the second one right above, I'm looking for the output of : 'ouncei uapoun ae tiomei'

but instead am finding myself with :

"ounceio uapoun aeio tiomeio"

How can I limit my loop to only replacing each character once?

Nick
  • 97
  • 3
  • 11

2 Answers2

2

Python 3's str.translate function does what you want. Note that the translation dictionary must use Unicode ordinals for keys, so the function uses a dictionary comprehension to convert it to the right format:

def encode(msg,code):
    code = {ord(k):v for k,v in code.items()}
    return msg.translate(code)

print(encode("blagh", {"a":"e","h":"r"}))
print(encode("once upon a time",{'a':'ae','e':'ei','i':'io','o':'ou','u':'ua'}))

Output:

blegr
ouncei uapoun ae tiomei

It works in Python 2 as well if you use Unicode strings or add the following to the top of the file to make strings Unicode by default:

from __future__ import unicode_literals
Mark Tolonen
  • 166,664
  • 26
  • 169
  • 251
1

Instead of using str.replace, replace character by character:

def encode(msg, code):
    result = ''
    for ch in msg:
        result += code.get(ch, ch)
    return result

Using generator expression:

def encode(msg, code):
    return ''.join(code.get(ch, ch) for ch in msg)
falsetru
  • 357,413
  • 63
  • 732
  • 636