Change each character in string to the next character in alphabet

前端 未结 8 1073
佛祖请我去吃肉
佛祖请我去吃肉 2021-01-03 15:45

I am coding in Python 2.7 using PyCharm on Ubuntu.

I am trying to create a function that will take a string and change each character to the character that would be

相关标签:
8条回答
  • 2021-01-03 16:15

    Two main things. 1) Don't use the Python built-in str to define variables as it could lead to unusual behaviour. 2) for letter in range(len(str)) does not return a letter at all (hence the error stating that 0 is not in your list). Instead, it returns numbers one by one up to the length of str. Instead, you can just use for letter in my_string.

    EDIT: Note that you don't need to convert the string into a list of letters. Python will automatically break the string into individual letters in for letter in strng. Updated answer based on comment from linus.

    def LetterChanges(strng):
        ab_st = list(string.lowercase)
        output_string = []
        for letter in strng:
            if letter == 'z':
                output_string.append('a')
            else:
                letter_index = ab_st.index(letter) + 1
                output_string.append(ab_st[letter_index])
            new_word = "".join(output_string)
    
        return new_word
    
    
    # keep this function call here
    print LetterChanges(raw_input())
    
    0 讨论(0)
  • 2021-01-03 16:15

    Here is a more general approach where user can choose how many characters back or forth they want to shift the string, and which alphabets they want to use:

    from string import (ascii_lowercase,
                        ascii_uppercase)
    from typing import Sequence
    
    
    def shift(string: str,
              *,
              alphabets: Sequence[str] = (ascii_lowercase, ascii_uppercase),
              step: int = 1) -> str:
        """Shifts `string` by `step` in `alphabets`"""
    
        def shift_char(char):
            for alphabet in alphabets:
                try:
                    return alphabet[(alphabet.index(char) + step) % len(alphabet)]
                except ValueError:
                    pass
            return char
    
        return ''.join(map(shift_char, string))
    

    Examples of usage:

    # default parameters
    >>> shift('abcxyz, ABCXYZ')
    'bcdyza, BCDYZA'
    
    # negative shift
    >>> shift('abcxyz, ABCXYZ',
             step=-1)
    'zabwxy, ZABWXY'
    
    # using other alphabets
    >>> russian_alphabet = 'абвгдеёжзийклмнопрстуфхцчшщъыьэюя'
    >>> shift('уегнп гбзмюсзм',
              alphabets=[russian_alphabet])
    'фёдор двинятин'
    

    Note on performance:

    Note that alphabet[(alphabet.index(char) + step) % len(alphabet)] is O(n) due to searching of an index of an element in a string. While for small strings it's ok, for large strings it would make sense to have a dictionary mapping each character in an alphabet to its index, like:

    mapping = dict(map(reversed, enumerate(alphabet)))
    
    0 讨论(0)
  • 2021-01-03 16:17

    The problem you are solving is of Ceaser cipher. you can implement the formula in your code.

    E(x) = (x+n)%26 where x is your text and n will be the shift.

    Below is my code. (I write the code in python 3)

    import ast
    n = ast.literal_eval(input())
    n1 = n[0]
    step = n[1]
    def enc_dec(string,step):
        result = ''
        for i in string:
            temp = ''
            if i=='':
                result = result+i
            elif i.isupper():
                temp = chr((ord(i) + step - 65) % 26 + 65)
            else:
                temp = chr((ord(i) + step - 97) % 26 + 97)
            result = result + temp
        return result
    print(enc_dec(n1,step))
    
    0 讨论(0)
  • 2021-01-03 16:17

    There's two issues with the code. Instead of looping letters you're looping over numbers since you're calling range(len(str)). The second issue is that within the loop you assign a string to new_word which will cause the next iteration to fail since string doesn't have method append. If you make the following changes it should work:

    for letter in str: # for letter in range(len(str)):
        if letter == "z":
            new_word.append("a")
        else:
            new_word.append(ab_st[str.index(letter) + 1])
        # new_word = "".join(new_word)
    new_word = "".join(new_word)
    
    0 讨论(0)
  • 2021-01-03 16:19

    Look at this for ideas to simplify your code.

    def LetterChanges(word):
        zabc  = 'abcdefghijklmonpqrstuvwxyzabc'
        ab_st = list(zabc)
        new_word = []    
        for letter in list(word.lower().strip()):        
            new_word.append(ab_st[zabc.index(letter) + 1])
        new_word = "".join(new_word)
        return new_word          
    
    
    LetterChanges("  Chicago ")
    
    0 讨论(0)
  • 2021-01-03 16:22

    I think you are making this too complicated.

    Just use modulo to roll around to the beginning of the string:

    from string import ascii_letters
    
    s='abcxyz ABCXYZ'
    ns=''
    for c in s:
        if c in ascii_letters:
            ns=ns+ascii_letters[(ascii_letters.index(c)+1)%len(ascii_letters)]
        else:
            ns+=c
    

    Which you can reduce to a single unreadable line if you wish:

    ''.join([ascii_letters[(ascii_letters.index(c)+1)%len(ascii_letters)] 
                 if c in ascii_letters else c for c in s])
    

    Either case,

    Turns      abcxyz ABCXYZ
    into       bcdyzA BCDYZa
    

    If you want it to be limited to upper of lower case letters, just change the import:

    from string import ascii_lowercase as letters
    
    s='abcxyz'
    ns=''
    for c in s:
        if c in letters:
            ns=ns+letters[(letters.index(c)+1)%len(letters)]
        else:
            ns+=c
    
    0 讨论(0)
提交回复
热议问题