Как читать строку по одной букве за раз в Python
Мне нужно преобразовать строку, введенную пользователем в азбуку Морзе. Наш профессор хочет, чтобы мы это делали, читая из файла morseCode.txt, разделяя буквы из morseCode в два списка, а затем преобразовывая каждую букву в код Морзе (вставляя новую строку, если есть пробел).
У меня есть начало. Он читает файл morseCode.txt и разделяет буквы в список [A, B, ... Z], а коды - в список ['- -., - - \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()
9 ответов
Почему бы просто не перебрать строку?
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"
?
Пара вещей для тебя:
Загрузка будет "лучше", как это:
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
Я не могу оставить этот вопрос в таком состоянии, когда этот окончательный код в вопросе висит над мной...
Дэн: вот гораздо более аккуратная и короткая версия вашего кода. Было бы неплохо взглянуть на то, как это делается, и больше писать код таким образом в будущем. Я понимаю, что вам, вероятно, больше не нужен этот код, но изучение того, как вы должны это делать, является хорошей идеей. Некоторые вещи на заметку:
Есть только два комментария - и даже второй действительно не нужен для тех, кто знаком с Python, они поймут, что NL удаляется. Пишите комментарии только там, где это добавляет ценность.
with
оператор (рекомендуется в другом ответе) устраняет необходимость закрытия файла через обработчик контекста.Используйте словарь вместо двух списков.
Генератор понимания (
(x for y in z)
) используется для перевода в одну строку.Оберните как можно меньше кода в
try
/except
блок, чтобы уменьшить вероятность получения исключения, которое вы не хотели.Использовать
input()
аргумент, а неprint()
сначала - используйте'\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")
# 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)
Используйте "индекс".
def GetMorseCode(letter):
index = letterList.index(letter)
code = codeList[index]
return code
Конечно, вы захотите проверить правильность введенного вами письма (при необходимости преобразуйте его регистр, убедитесь, что оно находится в списке, проверив этот индекс!= -1), но это должно помочь вам в этом.
Для фактической обработки я оставляю строку готового продукта и перебираю каждую букву в строке, которую они ввели. Я бы вызвал функцию для преобразования буквы в азбуку Морзе, а затем добавил ее в строку существующего азбуки Морзе.
finishedProduct = []
userInput = input("Enter text")
for letter in userInput:
finishedProduct.append( letterToMorseCode(letter) )
theString = ''.join(finishedProduct)
print(theString)
Вы можете проверить наличие места в цикле или в вызываемой функции.
# 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)
Сначала создайте таблицу поиска:
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')]
Вот простой пример: эта программа вычисляет, сколько пробелов в предложении.
# get an input from the user
inp = input("Write a sentence: ")
spaces = 0
for i in inp:
#print each letter the user have typed
if(i == " ")
spaces += 1
print(spaces)