word = input('input word you want to change letters in: ')

chars = tuple(word)
change_this = input('Enter the letters you want to change: ')
replace_with = input('Enter the letters to replace with: ')

if len(change_this) != len(replace_with):
     raise RuntimeError(
         "Letters to replace must be equals in number to letters you want " +
         "to change"
     )

change_chars = tuple(change_this)
replace_chars = tuple(replace_with)

new_chars = []

for ch in chars:
     try:
         i = change_chars.index(ch)
     except ValueError:
         new_chars.append(ch)
     else:
         new_chars.append(replace_chars[i])


There are two 'phases' to this program:

1 collecting the input-data, and
2 performing a translation.

The second and third inputs must be the same length - hence the first if-condition (above).


Phase 1:

More user-friendly (considerate) ways to do this include:

- (if short strings) input the character-pairs as a unit:-

    while ... # decide upon a sentinel/loop-terminator
        in = input( "A character and its replacement" )
        source_character, replacement_character = in.split( ... )
        # insert appropriate criteria as ...
        source_list.append( source_character )
        replacement_list.append( replacement_character )

- (existing practice) alter the input() "prompt-strings" to be the same length, and thus assist the user to *see* that his/her two inputs [must] also 'match' in length! eg

Source  characters? abcdef↵
Encoded characters? zyxwuv↵


Phase 2:

The translation phase is most easily achieved with the built-in str.translate() - and likely faster! First the translation-table must be built, then the source-text(s) translated:

    source_str = "".join( source_list )
    replacement_str = "".join( replacement_list )
    # have to join (above) lists into strings for next line
    translation_table = str.maketrans( source_str, replacement_str )
    translation = word.translate( translation_table )

NB because maketrans() is a static method (of the str[ing] class) we must use the "str.".

NBB because str.maketrans() checks the length of the two translation-strings, wrapping that with try...except might be considered more 'pythonic' than the "first if-condition" (although "explicit is better...", Zen of Python)


For extra credit/re-factoring further:
(after learning the above 'straight-line' approaches and code constructs)

str.maketrans() will accept a single dict[ionary]. Accordingly, instead of collecting the translation data as two lists - which must then be converted into strings; (no matter which approach to 'phase 1' is preferred); consider building a translation-dictionary wherein each entry has the 'letter to be changed' as its "key", and its "data" is 'the letter to replace [it] with'. Refactoring from the above:

    source_character, replacement_character = in.split( ... )
    translation_dict[ source_character ] = replacement_character
    translation_table = str.maketrans( translation_dict )
    translation = word.translate( translation_table )


Trust this adds to your 'adventures' in learning Python!


Web.Refs:
https://docs.python.org/3/library/stdtypes.html#text-sequence-type-str
https://www.askpython.com/python/string/python-string-translate
--
Regards =dn
--
https://mail.python.org/mailman/listinfo/python-list

Reply via email to