【问题标题】:Change each character in string to the next character in alphabet将字符串中的每个字符更改为字母表中的下一个字符
【发布时间】:2016-06-05 15:47:17
【问题描述】:

我在 Ubuntu 上使用 PyCharm 在 Python 2.7 中进行编码。

我正在尝试创建一个函数,该函数将接受一个字符串并将每个字符更改为字母表中的下一个字符。

def LetterChanges(str):
    # code goes here
    import string
    ab_st = list(string.lowercase)
    str = list(str)
    new_word = []
    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)
    return new_word


# keep this function call here
print LetterChanges(raw_input())

运行代码时出现以下错误:

/usr/bin/python2.7 /home/vito/PycharmProjects/untitled1/test.py
test
Traceback (most recent call last):
  File "/home/vito/PycharmProjects/untitled1/test.py", line 17, in <module>
    print LetterChanges(raw_input())
  File "/home/vito/PycharmProjects/untitled1/test.py", line 11, in LetterChanges
    new_word.append(ab_st[str.index(letter) + 1])
ValueError: 0 is not in list

Process finished with exit code 1

第 11 行我在做什么?如何获取字母表中每个字符的以下字符并将其附加到新列表中?

非常感谢。

【问题讨论】:

标签: python string python-2.7


【解决方案1】:

我认为你把这件事弄得太复杂了。

只需使用模数滚动到字符串的开头:

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

如果您愿意,您可以将其简化为一个不可读的行:

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

无论哪种情况,

Turns      abcxyz ABCXYZ
into       bcdyzA BCDYZa

如果你希望它限制为大写字母,只需更改导入:

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

【讨论】:

  • 我更喜欢这种方法而不是我自己的答案。我专门尝试处理 OP 代码中的错误。点赞:)
【解决方案2】:

两个主要的东西。 1) 不要使用 Python 内置的 str 来定义变量,因为它可能导致异常行为。 2)for letter in range(len(str)) 根本不返回字母(因此错误指出 0 不在您的列表中)。相反,它会一一返回数字,直到 str 的长度。相反,您可以使用for letter in my_string

编辑:请注意,您不需要将字符串转换为字母列表。 Python 会自动将字符串分解为for letter in strng 中的单个字母。根据 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())

【讨论】:

    【解决方案3】:

    这是我的代码,我认为它很简单

    def LetterChanges(st):
        index = 0
        new_word = ""
        alphapet = "abcdefghijklmnopqrstuvwxyzacd"
    
        for i in st.lower():
            if i.islower(): #check if i s letter
                index = alphapet.index(i) + 1 #get the index of the following letter
                new_word += alphapet[index]    
            else: #if not letter
                new_word += i    
        return new_word
    
    
    print LetterChanges(raw_input())
    

    【讨论】:

      【解决方案4】:

      您正在解决的问题是 Ceaser 密码。您可以在代码中实现该公式。

      E(x) = (x+n)%26 其中 x 是您的文本,n 将是班次。

      下面是我的代码。 (我用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))
      

      【讨论】:

        【解决方案5】:

        代码有两个问题。因为你调用range(len(str)),所以不是循环字母,而是循环数字。第二个问题是,在循环中,您将字符串分配给new_word,这将导致下一次迭代失败,因为string 没有方法append。如果您进行以下更改,它应该可以工作:

        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)
        

        【讨论】:

          【解决方案6】:

          查看此内容以获得简化代码的想法。

          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 ")
          

          【讨论】:

          • zabc 如何比string.lowercase 更容易做到这一点?
          • 你在'z'之后添加了'a',所以你删除了if“z”语句,你不需要导入“string”。 string.lowercase 没有什么意义。你能阅读其余的代码吗?什么是“字符串”。定义变量时尽量描述性强,避免python关键字
          • 我不是 OP,我想你误会了?输入字母肯定不是一个解决方案,尤其是当它可以是任意长度时。
          • 这不是 OP 想要的。而且,在 RegEx 中也可以使用字符串。
          • 我很困惑。我不确定输入字母如何提供比 OP 使用的更好的解决方案。我只是好奇你为什么要换人。
          【解决方案7】:

          这是一种更通用的方法,用户可以选择他们想要前后移动多少个字符,以及他们想要使用哪些字母:

          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))
          

          使用示例:

          # 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])
          'фёдор двинятин'
          

          性能说明:

          请注意,alphabet[(alphabet.index(char) + step) % len(alphabet)]O(n),因为它在字符串中搜索元素的索引。虽然对于小字符串没关系,但对于大字符串,有一个字典将字母表中的每个字符映射到它的索引是有意义的,比如:

          mapping = dict(map(reversed, enumerate(alphabet)))
          

          【讨论】:

            【解决方案8】:

            通过使用查找而不是对每个字母使用index,可以更轻松、更有效地完成此操作。

            look_up = dict(zip(string.ascii_lowercase, string.ascii_lowercase[1:]+'a'))
            

            上面的zip 创建了('a', 'b')... 形式的元组,包括('z', 'a')。将其输入dict 构造函数会生成相同形式的字典。

            所以现在代码可以很简单:

            def LetterChanges(s):
                from string import ascii_lowercase
                
                look_up = dict(zip(ascii_lowercase, ascii_lowercase[1:]+'a'))
                new_s = ''
                for letter in s:
                    new_s += look_up[letter]
            
                return new_s
            

            即使这个 dict 创建和循环也可以通过使用 str.maketrans 方法并将其结果提供给 str.translate 来保存:

            def LetterChanges(s):
                from string import ascii_lowercase
            
                return s.translate(str.maketrans(ascii_lowercase, ascii_lowercase[1:]+'a'))
            

            【讨论】:

              猜你喜欢
              • 2018-06-07
              • 1970-01-01
              • 1970-01-01
              • 2017-07-14
              • 2013-03-07
              • 1970-01-01
              • 2010-11-16
              • 1970-01-01
              相关资源
              最近更新 更多