【问题标题】:How to read a string one letter at a time in python如何在python中一次读取一个字母的字符串
【发布时间】:2011-02-07 16:51:52
【问题描述】:

我需要将用户输入的字符串转换为莫尔斯电码。我们的教授希望我们这样做的方式是从 morseCode.txt 文件中读取,将 morseCode 中的字母分成两个列表,然后将每个字母转换为莫尔斯电码(当有空格时插入新行)。

我有一个开始。它所做的是读取 morseCode.txt 文件并将字母分成列表 [A, B, ... Z] 并将代码分成列表 ['– – 。 . - -\n','。 – 。 – 。 –\n'...]。

我们还没有学过“集合”,所以我不能用它。然后我将如何获取他们输入的字符串,逐个字母地遍历并将其转换为莫尔斯电码?我有点赶上。这是我现在拥有的(一点也不多……)

编辑:完成程序!

# open morseCode.txt file to read
morseCodeFile = open('morseCode.txt', 'r') # format is <letter>:<morse code translation><\n>   
# create an empty list for letters
letterList = []    
# create an empty list for morse codes
codeList = []
# read the first line of the morseCode.txt
line = morseCodeFile.readline()    
# while the line is not empty
while line != '':        
    # strip the \n from the end of each line
    line = line.rstrip()        
    # append the first character of the line to the letterList        
    letterList.append(line[0])           
    # append the 3rd to last character of the line to the codeList
    codeList.append(line[2:])        
    # read the next line
    line = morseCodeFile.readline()        
# close the file    
morseCodeFile.close()


try:
    # get user input
    print("Enter a string to convert to morse code or press <enter> to quit")    
    userInput = input("")  
    # while the user inputs something, continue   
    while userInput:
        # strip the spaces from their input
        userInput = userInput.replace(' ', '')
        # convert to uppercase
        userInput = userInput.upper()

        # set string accumulator
        accumulateLetters = ''
        # go through each letter of the word
        for x in userInput:            
            # get the index of the letterList using x
            index = letterList.index(x)
            # get the morse code value from the codeList using the index found above
            value = codeList[index]
            # accumulate the letter found above
            accumulateLetters += value
        # print the letters    
        print(accumulateLetters)
        # input to try again or <enter> to quit
        print("Try again or press <enter> to quit")
        userInput = input("")

except ValueError:
    print("Error in input. Only alphanumeric characters, a comma, and period allowed")
    main()   

【问题讨论】:

  • 我知道您的老师会鼓励您对代码进行评论,但您也应该学习仅在他们添加有用的东西时使用它们;-)(例如文档 API,参考您的公式或数据表的位置取自,解释为什么在似乎有另一种更简单的情况下以某种方式做某事等)
  • 考虑将 try/except 内容放在 for x in inputLetters 循环中。这样,您可以“接受”超出范围的字符,然后继续转换所有其余字符。此外,您不需要删除前面的所有空格。
  • 感谢 cmets 的各位。 dash-tom-bang,我通过附加列表来编辑程序以允许空格。感谢fortran,但不幸的是老师让我们编写程序的方式,她希望我们先用所有伪代码编写它,然后再回去用实际代码填充它。所以如果没有评论,她会知道我们没有先做伪代码。不过,我感谢你们所有人的帮助!

标签: python


【解决方案1】:

为什么不只遍历字符串?

a_string="abcd"
for letter in a_string:
    print letter

返回

a
b
c
d

所以,在伪代码中,我会这样做:

user_string = raw_input()
list_of_output = []
for letter in user_string:
   list_of_output.append(morse_code_ify(letter))

output_string = "".join(list_of_output)

注意:morse_code_ify 函数是伪代码。

肯定想要列出要输出的字符,而不仅仅是在某个字符串的末尾连接它们。如上所述,它是 O(n^2): 不好。只需将它们附加到列表中,然后使用"".join(the_list)

附带说明:为什么要删除空格?为什么不让morse_code_ify(" ") 返回"\n"

【讨论】:

    【解决方案2】:

    给你的几件事:

    加载会像这样“更好”:

    with file('morsecodes.txt', 'rt') as f:
       for line in f:
          line = line.strip()
          if len(line) > 0:
             # do your stuff to parse the file
    

    这样就不需要关闭,也不需要手动加载每一行等等等等

    for letter in userInput:
       if ValidateLetter(letter):  # you need to define this
          code = GetMorseCode(letter)  # from my other answer
          # do whatever you want
    

    【讨论】:

    • +1 那是很好的 python 风格...学习这个,你会在剩下的课程和 python 生活中节省很多代码。
    • len(line) 总是正数,因为它总是至少包含行尾字符
    【解决方案3】:

    使用“索引”。

    def GetMorseCode(letter):
       index = letterList.index(letter)
       code = codeList[index]
       return code
    

    当然,您需要验证您的输入字母(根据需要转换其大小写,首先通过检查该索引!= -1 确保它在列表中),但这应该会让您走上正轨.

    【讨论】:

    • +1 既是为了回答问题,也是为了迫使提问者单独完成项目。
    【解决方案4】:
    # Retain a map of the Morse code
    conversion = {}
    
    # Read map from file, add it to the datastructure
    morseCodeFile = file('morseCode.txt')
    for line in moreCodeFile:
        conversion[line[0]] = line[2:]
    morseCodeFile.close()
    
    # Ask for input from the user
    s = raw_input("Please enter string to translate")
    # Go over each character, and print it the translation.
    # Defensive programming: do something sane if the user 
    # inputs non-Morse compatible strings.    
    for c in s:
        print conversion.get(c, "No translation for "+c)
    

    【讨论】:

    • 这个用不了,没学这么多。我已经编辑了我的原始帖子以包含更多代码。只是需要帮助完成它
    • 你所拥有的“到目前为止”并没有真正起作用,所以很难“完成它”。哪些部分你没学过?
    • 还没学过地图。如果您查看我的编辑,为什么我不能使用循环来遍历去除空格的字符串,获取当前字母并在 letterList 列表中搜索其索引,然后使用相应的位置查找莫尔斯电码列表中的莫尔斯电码,并返回
    • 哎哟。这就像慢慢地写自己的地图。你可以这样做,但这太可怕了。 [这与你所拥有的“到目前为止”是不正确的事实无关,真的。例如,“morseCodeFile.rstrip()”将失败。但我不确定“在没有地图的情况下学习使用 Python”有多大的教学价值——映射 Python 的灵魂......]
    • 好吧,我修复了 rstrip() 行。现在是 line = line.rstrip() 所以这不是问题所在。这很糟糕:(
    【解决方案5】:

    我不能把这个问题留在这个状态,问题中的最终代码悬在我头上......

    dan:这是您的代码的更简洁和更短的版本。看看这是如何完成的并在未来以这种方式编写更多代码将是一个好主意。我意识到您可能不再需要此代码,但学习如何做是个好主意。需要注意的几点:

    • 只有两个 cmets - 对于熟悉 Python 的人来说,即使第二个也不是必需的,他们会意识到 NL 正在被剥离。只在能增加价值的地方写 cmets。

    • with 语句(在另一个答案中推荐)消除了通过上下文处理程序关闭文件的麻烦。

    • 使用字典而不是两个列表。

    • 生成器理解 ((x for y in z)) 用于在一行中进行翻译。

    • 将尽可能少的代码封装在 try/except 块中,以降低捕获您无意捕获的异常的可能性。

    • 首先使用input() 参数而不是print()ing - 使用'\n' 来获得所需的新行。

    • 不要仅仅为了它而跨多行或使用这样的中间变量编写代码:

      a = a.b()
      a = a.c()
      b = a.x()
      c = b.y()
      

      相反,像这样编写这些结构,将调用链接起来是完全有效的:

      a = a.b().c()
      c = a.x().y()
      

    code = {}
    with open('morseCode.txt', 'r') as morse_code_file:
        # line format is <letter>:<morse code translation>
        for line in morse_code_file:
            line = line.rstrip()  # Remove NL
            code[line[0]] = line[2:]
    
    user_input = input("Enter a string to convert to morse code or press <enter> to quit\n")
    while user_input:
        try:
            print(''.join(code[x] for x in user_input.replace(' ', '').upper()))
        except KeyError:
            print("Error in input. Only alphanumeric characters, a comma, and period allowed")
    
        user_input = input("Try again or press <enter> to quit\n")
    

    【讨论】:

      【解决方案6】:
      # Open the file
      f = open('morseCode.txt', 'r')
      
      # Read the morse code data into "letters" [(lowercased letter, morse code), ...]
      letters = []
      for Line in f:
          if not Line.strip(): break
          letter, code = Line.strip().split() # Assuming the format is <letter><whitespace><morse code><newline>
          letters.append((letter.lower(), code))
      f.close()
      
      # Get the input from the user
      # (Don't use input() - it calls eval(raw_input())!)
      i = raw_input("Enter a string to be converted to morse code or press <enter> to quit ") 
      
      # Convert the codes to morse code
      out = []
      for c in i:
          found = False
          for letter, code in letters:
              if letter == c.lower():
                  found = True
                  out.append(code)
                  break
      
          if not found: 
              raise Exception('invalid character: %s' % c)
      
      # Print the output
      print ' '.join(out)
      

      【讨论】:

        【解决方案7】:

        对于实际处理,我会保留一串成品,并遍历他们输入的字符串中的每个字母。我会调用一个函数将字母转换为莫尔斯电码,然后将其添加到现有的莫尔斯电码字符串中。

        finishedProduct = []
        userInput = input("Enter text")
        for letter in userInput:
            finishedProduct.append( letterToMorseCode(letter) )
        theString = ''.join(finishedProduct)
        print(theString)
        

        您可以检查循环中的空间,也可以检查被调用的函数中的空间。

        【讨论】:

        • 没关系,我只是无法将字符串拆分为单个字母
        • 在 Python 中以这种方式构建字符串是个坏主意——它是 O(N**2)。建立一个列表,然后用 "".join(l) 加入它,然后打印出来。
        【解决方案8】:

        先创建一个查找表:

        morse = [None] * (ord('z') - ord('a') + 1)
        for line in moreCodeFile:
            morse[ord(line[0].lower()) - ord('a')] = line[2:]
        

        然后使用表格进行转换:

        for ch in userInput:
            print morse[ord(ch.lower()) - ord('a')]
        

        【讨论】:

        • 哎哟。不要更改 range 的返回值——它恰好可以工作,但它不是真正受支持或不是很好的风格。如果你想要一个给定长度的列表,morse = [None]*(ord('z')-(ord('a')) 会更好
        猜你喜欢
        • 2014-03-21
        • 1970-01-01
        • 2012-04-08
        • 2013-06-27
        • 2021-07-06
        • 2011-02-28
        • 1970-01-01
        • 2012-10-16
        相关资源
        最近更新 更多