【问题标题】:How to replace characters in a string using iteration and variables? (Python)如何使用迭代和变量替换字符串中的字符? (Python)
【发布时间】:2014-02-05 13:18:54
【问题描述】:

作为大学项目的一部分,我正在用 python 编写一个刽子手游戏,我正在尝试使用 string.replace(old, new) 将空格 (_) 替换为字母。不过,我没有使用实际的字符串字符,而是尝试将变量用于“旧”和“新”。到目前为止,这是我对这一点的了解:

if validGuess == 'true':
    if guess in word:
        for letter in word:
            if letter == guess:
                word.replace(letter, guess)
            else:
                missNum = (missNum + 1)
    else:
        tryNum = (tryNum - 1)

但是,它不起作用。我没有收到任何错误,它根本不会替换空白。

我在这里做错了什么?有没有更好的方法来实现我正在做的事情?

-编辑-

我尝试实施@Peter Westlake 的解决方案(在我看来这是最优雅的),但我遇到了问题。我有一段代码将随机选择的单词转换为下划线:

#converting word to underscores
wordLength = len(word)
wordLength = (wordLength - 1)
print(wordLength) #testing
for i in range(0,wordLength):
    wordGuess = (wordGuess + '_')
print(wordGuess)

这似乎工作正常。这是字母替换的代码:

if validGuess == 'true':
    wordGuess = ''.join([letter if guess == letter else wordGuess[pos]
                         for pos, letter in enumerate(word)])

    if guess not in word:
        tryNum = (tryNum - 1)

    print(wordGuess)

但是,这里是输出:

Guess a letter: a
test
Traceback (most recent call last):
  File "G:\Python\Hangman\hangman.py", line 60, in <module>
    for pos, letter in enumerate(word)])
  File "G:\Python\Hangman\hangman.py", line 60, in <listcomp>
    for pos, letter in enumerate(word)])
IndexError: string index out of range

字符串索引超出范围?这是什么意思?

【问题讨论】:

  • 我不确定你的情况,if letter == guess你需要在这里更换什么?
  • 你能把你的输入和预期输出。
  • "String index out of range" 表示您试图从字符串末尾获取一个字母,这是因为您从 wordLength 中减去 1。 range(x,y) 给出了从 x 到 y-1 的所有数字,因此无需再次减 1。一个更简单的方法是:wordGuess = '_' * len(word).

标签: python string variables replace iteration


【解决方案1】:

str.replace() 返回新字符串,存储新值:

word = word.replace(letter, guess)

Python 字符串是不可变的,不能就地更改。

但是,您将 letter 替换为完全相同的值; letter == guess 只有在两个字符相同时才为 True。

我会保留一组单独的正确猜测的字母,并重建显示的下划线并每次正确猜测:

correct_guesses = set()
incorrect_guesses = set()

if guess in correct_guesses & incorrect_guesses:
    print('You already guessed that letter')

elif guess in word:
    # correct guess!
    correct_guesses.add(guess)
    display_word = ''.join(char if char in correct_guesses else '_' for char in word)

else:
    # incorrect guess!
    incorrect_guesses.add(guess)
    print('Oops, incorrect guess!')
    missNum += 1

【讨论】:

  • 只是一个猜测,因为我不是反对者,但是:您在编写的 OP 代码中发现了一个小错误,但整个算法也是错误的,您的答案没有解决那。作为评论可能会更好。
  • Hrm,我本来打算回到这篇文章来扩展。我在不止一个帖子上收到了多次反对票,所以我实际上假设一个连续反对票的人在工作。
  • 我有一个先前猜测的字母的黑名单已经在代码的不同部分,但我喜欢你在这里所做的,我可能需要考虑单独存储猜测的字母......
【解决方案2】:

我想我明白你在这里的意思。

我可能会在现场重建这个词,而不是为它保留一个持久的字符串,将测试的字母分开保存。当用户尝试一个新角色时,进行两次检查:

  1. 查看猜测字符是否已经被猜测:if guess in tried。如果是这样,按照你喜欢的方式继续(惩罚或忽略),但不要将字符添加到尝试字符列表中。

  2. 如果不是,查看该字符是否在目标词中:elif guess in word。如果不是,请评估一些惩罚并将猜测添加到已尝试字符列表中。

  3. 对于任何其他结果:else。将猜测添加到尝试过的字符列表中。

要显示用户的进度,请创建一个空白字符串。一次遍历目标单词字符:for char in word,就像你一样。但与其尝试修改现有字符串,只需将字符添加到空字符串的末尾(如果它在尝试字符字符串中),或者如果不是,则添加下划线:show += char if char in tried else "_"。一旦 for 循环用完,显示你所拥有的!

或者,使用 .join 和稍微不同的迭代器:show = "".join(char if char in tried else '_' for char in word)。它将遍历单词,如果每个字母都在您尝试过的字符字符串中,则保留它,如果不是,则替换下划线,将 "" 中的任何内容放在它们之间(或者什么都没有,如果您将其保留为 "")。不过,您似乎已经知道了。

冒着完全重写代码的风险,它可能看起来像这样:

  ## init
word = "mauritius" # the word you're looking for. I chose this one.
tried = str()  # initialize a list of tested characters
tryNum = 3  # however many wrong guesses the user gets

  ...

  ## in your run loop...
if tryNum:  # evaluates 0 as Fasle, if you didn't already know
    guess = UserInput()  # some means to get the guess from the user; a single-character string.

    if   guess in tried:
        print "Tried that letter already!" 
    elif guess not in word:   # the letter hasn't been tested yet, but isn't in the word, either.
        print "Wrong! %d guesses left!" % tryNum
        tryNum -= 1
        tried += guess
    else:    # the guess is new (not tried) and it's valid (in the word)
        tried += guess

    show = str()  # this is the string you will display. make a blank one each time.
    for char in word:
        show += char if char in tried else "_"  # if the character has been tried, add it to the output. Otherwise, an underscore.
    print show  # display the word so far

    if show == word:
        print "You win!" # Congratulations! You hung a man.

else:  # Out of tries; the convict lives another day.
    print "Game Over!" # I am not sure how committed to this vocabulary-based execution you really are...

您可以将if tryNum:while tryNum: 交换,它应该在初始化后自行工作。如果你这样做了,你可以用continues 和breaks 做一些有趣的事情,但这有点超出你的问题范围。

在下一个示例中,您也可以将 show = str()for char in word: 块与 .join 单例交换。将''.join(..) 更改为' '.join(..) 以在字符/下划线之间添加一个空格!

这个压缩版本可能有点不那么 Pythonic:

# post-init...
if tryNum:
    guess = UserInput()
    if guess in tried: pass
    elif guess not in word:
        print "Wrong! %d guesses left!" % tryNum
        tryNum -= 1
        tried  += guess
    else: tried += guess
    show = ''.join(char if char in tried else '_' for char in word)
    if show == word: print "You win!"
else: print "Game Over!"

这并没有回答您的第一个问题“我做错了什么?”但我认为这可能是一种更好的方式来实现你的意图?它也可能更容易维护和扩展。

注意:如果您想自己尝试一下,请将 UserInput() 替换为 str(raw_input("Guess a letter!"))[0] 之类的东西。

【讨论】:

  • 我想我不必太担心你的功课,因为我迟了十个月才回答......我希望这里的一些想法对你仍然有用(和未来的观众),不过......
  • 您好,感谢您的回复。哈哈,是啊,这个任务早就过去了!但是你在这方面确实有一些很好的观点,所以再次感谢 - 我相信将来看到这个的人会发现它有用。我最终设法让程序运行良好,如果有人感兴趣,我可以在这里发布?
  • @James.D.Wood 您可以将其发布为答案,当然!只要确保你把它作为一个正确的答案,而不仅仅是一个工作代码块! ;)
【解决方案3】:

用相同的猜测替换一个字母不会有任何作用!我想你想在单词中找到猜测的字母出现的位置,并将该位置的_ 替换为该字母。为此,您需要找到字母出现的每个位置,例如使用index() 方法。

例如,替换第一次出现的猜测:

# Illustration of the principle, not the complete answer.

word = 'faq'
display = '___'

# Put in a loop, one iteration for each guess input.
guess = 'a'
display = ''.join([letter if guess == letter else display[pos]
                   for pos, letter in enumerate(word)])
print display

这将打印_a_

【讨论】:

  • 我喜欢这个解决方案......但我似乎无法让它按照我想要的方式工作。检查 OP 的详细信息......非常感谢!
猜你喜欢
  • 2011-10-28
  • 1970-01-01
  • 2021-05-15
  • 2021-10-27
  • 1970-01-01
  • 2020-07-09
  • 2017-06-29
  • 2011-10-23
  • 1970-01-01
相关资源
最近更新 更多