4

I have researched about character replacement using dictionaries but I still cannot get my code to work properly. My code goes like this:

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

Now, when I run the code:

code = {'e':'x','x':'e'}
msg = "Jimi Hendrix"
encode(code,msg)

It gives me "Jimi Hxndrix" instead of "Jimi Hxndrie". How do I get the letter 'x' to be replaced by 'e' also?

2
  • 2
    You are replacing only the first occurrence of x for e, then the first occurrence of e for x. Thus, Jimi Hendrix becomes Jimi Hendrie, then Jimi Hxndrie. .replace() is not doing what you think it does. Commented Nov 29, 2012 at 13:27
  • @Martjin Pieters No. If one executes msg = msg.replace(k,code[k]) followed by print k,' ',msg on "Jimi Hendrix fixed the axes" , it prints firstly Jimi Hendrie fieed the aees then Jimi Hxndrix fixxd thx axxs . That's because code is a dictionary that is not iterated in the order 'e' then 'x' but in the order 'x' first and 'e' after. And all the occurences of a character in a string are replaced, not only the first one. Commented Nov 29, 2012 at 14:00

5 Answers 5

9

You can look at str.translate or do:

''.join(code.get(ch, ch) for ch in msg)
Sign up to request clarification or add additional context in comments.

Comments

2

Use maketrans and translate:

from string import maketrans
msg.translate(maketrans(''.join(code.keys()), ''.join(code.values())))

2 Comments

I think that the correct way should be msg.translate(maketrans(''.join(code.values()), ''.join(code.keys()))) instead of msg.translate(maketrans(''.join(code.keys()), ''.join(code.values()))) Although, in this case the result would be the same.
@Nikpa usually you'd write the dictionary as {from: to}.
0

The problem is that you iterate on code instead on msg

Iterating on msg is what is done in Jon Clements' program, which can be written more explicitly as

print ''.join(code[ch] if ch in code else ch for ch in msg)

Comments

0

you're swapping x and e; it is overwriting your previous edits.

You should copy from an old string to a new one (or rather, an array of chars, since as Kalle pointed out strings are "immutable"/not editable), so that you don't overwrite characters you've already replaced:

def encode(code, message):
    encoded = [c for c in message]
    for i, c in enumerate(message):
        try:
            encoded[i] = code[c]
        except KeyError:
            pass
    return ''.join(encoded)

the other answers are library functions which do something like this, but they don't explain where you went wrong.

2 Comments

Does not work, since strings are immutable, i.e. you may not change an existing string using operations like encoded[i] = code[c]
thanks, missed that. now using an array of chars instead. (I'm sure that would work in Ruby - I never figured out the differences in string handling in both languages. I use python a lot, just not for string operations!)
0
     python 3.2
     use your own code it is ok.

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

       ##  str.replace(old,new,[,count])
      so when you loop in your code = {'e':'x','x':'e'}
      first it gets the key "x" then the key "e" because dict is not ordered
      so,  "Hendrix" turns into "Hendrie" then "Hendrie" turns into Hxndrix and
     you are not having your result. but if you add 1 in your code
      msg.replace(k,code[k],1) then it only will replace one letter per loop and you                                    
      have your result Try.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.