Change the values of a list without using index

74 Views Asked by At
def apply_coder(text, coder):
    """
    Applies the coder to the text. Returns the encoded text.

    text: string
    coder: dict with mappings of characters to shifted characters
    returns: text after mapping coder chars to original text
    """

    coder_dict = coder
    text_list = list(text)
    for letter in text_list:
        if letter in coder_dict:
            letter = coder_dict[letter]
            print letter
    return ''.join(text_list)

Example: apply_coder("Hello, world!", build_encoder(3)) should return

'Khoor,czruog!'

Instead, it returns

"Hello, world!"

However, if I use a print letter statement in if condition it prints correct letters.

4

There are 4 best solutions below

0
On

By changing letter you are not changing anything in the list text_list. You should build a new list instead of the result of the encoding:

def apply_coder(text, coder):
    ret_val = []
    coder_dict = coder
    for letter in text:
        if letter in coder_dict:
            letter = coder_dict[letter]
            print letter
        ret_val.append(letter)
    return ''.join(ret_val)

And that also means you don't first have to make text into a list.

0
On

The statement letter = coder_dict[letter] just looks up the letter key in coder_dict and assigns that value to letter, which doesn't change it. The it prints that letter. However, you're not modifying text_list at all. There are several ways to do this, such as with enumerate:

def apply_coder(text, coder):
    text_list = list(text)
    for val,letter in enumerate(text_list):
        text_list[val] = coder.get(letter, letter)
    return ''.join(text_list)

This will enumerate the list, then reassign each indexed element with the letter lookup if possible or the letter itself otherwise, then join() the list and return it.

0
On

Rebinding the current iteration variable doesn't modify the list (hopefully - that would be a very annoying side effect).

Also, rebinding coder to coder_dict is useless, and you can iterate on a string. To make a long story short, the solution is to rebuild a list with the modified letters... and since you don't really need the list itself, you can as well just use a generator expression:

def apply_coder(text, coder):
    return ''.join(coder.get(letter, letter) for letter in text)
0
On

This is very similar to a question asked not long ago, about encrypting/swapping letters.

The code below is provided by alec_djinn

decrypted = 'abcdefghijklmnopqrstuvwxyz' #normal alphabet
encrypted = 'MNBVCXZLKJHGFDSAPOIUYTREWQ' #your "crypted" alphabet

#Encription
text = 'cryptme' #the string to be crypted
encrypted_text = ''
for letter in text:
    encrypted_text += encrypted[decrypted.find(letter)]
print encrypted_text
#will print BOWAUFC

#Decription
text = encrypted_text #"BOWAUFC" in this example
decrypted_text = ''
for letter in text:
    decrypted_text += decrypted[encrypted.find(letter)]
print decrypted_text
#will print cryptme

A link to this is provided below as well.

How to 'encrypt' a file