Python: изменение определенной позиции в строке
Это мой первый пост, и я ценю помощь.
Я работаю над проблемой в Python, где мне нужно создать программу для палача, и я столкнулся с проблемой, в которой я немного застрял. У меня есть рамки того, что я хочу сделать, но я застрял в синтаксисе.
По сути, я пишу функцию, в которой, учитывая слово и список букв, я должен вернуть строку, которая показывает, какие буквы были правильными догадками, а какие места в слове по-прежнему пустыми. Например, если секретным словом является "яблоко", а угаданный список букв - ['e', 'i', 'k', 'p', 'r', 's'], то функция должна вернуть '_ pp_ e'.
Мой подход к решению этой проблемы заключается в создании переменной для секретного слова и итерации по каждой букве, чтобы проверить, находится ли она в списке угаданных букв. Если это в списке, письмо останется; если нет, он будет заменен на "_". После завершения итерации функция вернет переменную secretWord.
Вот мой код до сих пор:
def getGuessedWord(secretWord, lettersGuessed):
'''
secretWord: string, the word the user is guessing
lettersGuessed: list, what letters have been guessed so far
returns: string, comprised of letters and underscores that represents
what letters in secretWord have been guessed so far.
'''
for i in secretWord:
if i not in lettersGuessed:
secretWord[len(i)] == '_ '
return secretWord
Моя проблема с третьей строкой в функции (secretWord[len(i)] == '_ '). Я не могу понять, как заставить Python заменить букву, которую я хочу, на '_'. Поскольку 'i' - это символ, а не целое число, я не могу сказать secretWord[i] = '_ '. Я признаю, что я немного новичок, и мне все еще сложно манипулировать строками, поэтому для кого-то с большим опытом это, вероятно, действительно легко исправить.
Еще раз спасибо за вашу помощь!
1 ответ
Что вы пытались сделать
Прежде всего, вы боретесь, потому что вы не знаете, как ссылаться на индекс буквы, которую вы хотите заменить. Когда вы делаете for i in secretWord
действительно, вы не получите переменную, которая содержит индекс; в вашем коде, ваш i
переменная содержит саму букву. Python предоставляет удобную функцию для случаев, когда вы хотите зациклить некоторую коллекцию, но вы также хотите отслеживать индекс во время зацикливания:
for i, letter in enumerate(secretWord):
if letter not in lettersGuessed:
# WATCH OUT: == is for comparison (is this equal to that?)
# = is for assignment (make this equal to that)
secretWord[i] = '_ '
enumerate
генерирует список (индекс, контент) кортежей, в которые вы разбиваете i
а также letter
переменные.
Вот код, который вы пытались написать. Buuut...
... это не сработает.
Решение
Это потому, что строки в Python неизменны - как только вы создадите их, вы не сможете их изменить. Это может показаться ужасно запретным, но вместо этого вы создаете измененные копии строк и присваиваете их различным переменным (или даже той же переменной, которая изначально содержала другую строку). Вы могли бы делать это все время, не осознавая. Но то, что вы определенно не можете сделать, это напрямую назначить что-то другое части существующей строки.
@DannyMoshe указал, как вы можете обойти это. replace
Метод дает вам копию строки, к которой он был вызван, и выполняет поиск и замену. Теперь вы можете назначить эту копию вашему оригиналу secretWord
переменная: secretWord = secretWord.replace(letter, '_ ')
, Ваша оригинальная строка выбрасывается, а ваша secretWord
переменная теперь ссылается на вновь сгенерированную строку. (Да, требуется немного практики, чтобы понять разницу между мутированием и копированием; и да, это сбивает с толку то, что назначение новой строки переменной не классифицируется как мутирование, а назначение новой буквы индексированной позиции в этой переменной.)
Улучшение
Проблема в том, что вы неоднократно выбрасываете свой старый secretWord
s и заменяя их копиями, в которых постепенно появляется больше "_". Прежде всего, вам может понадобиться обратиться к оригиналу secretWord
снова внутри той же самой функции (вне функции она не изменилась - она была скопирована, когда она была передана функции!), и поэтому всегда полезно создать отдельную переменную для такого рода вещей. Назови это output
или же displayWord
или что-то. Во-вторых, все это копирование и выбрасывание неэффективно. Итак, в заключение, я покажу вам способ сделать это, используя понимание списка, которое, если вы еще не сталкивались с этим, является одной из самых элегантных функций Python и часто более эффективно, чем его эквивалентная формулировка цикла.
displayWord = ''.join(letter if letter in lettersGuessed else '_ ' for letter in word)
Вот и все. Вы могли бы заменить displayWord =
с return
и иметь функцию в одну строку. Чтобы быть понятным, часть понимания списка [letter if letter in lettersGuessed else '_ ' for letter in word]
, но это создает список. Чтобы превратить список в строку, которую вы используете ''.join()
(и в этом контексте вы можете опустить квадратные скобки самого понимания списка).
И последнее. Если secretWord = "caligula"
а также lettersGuessed = "aei"
, displayWord
было бы _ a_ _ _ u_ a
, Обратите внимание на смещения для букв, где вы не вставили пробел. Есть отличный способ это исправить. Вы, наверное, интересуетесь странным синтаксисом ''.join()
, То, что мы делаем, называется join
метод на пустой строке. Какую бы строку мы ни называли join
on действует как разделитель между элементами списка при склеивании списка. Таким образом, если мы хотим, чтобы наши displayWord
все аккуратно разнесено, мы могли бы написать:
# (note where I've put the space)
displayWord = ' '.join(letter if letter in lettersGuessed else '_' for letter in word)